// src/createViteDevServer.ts
import { createServer as createViteServer } from "vite";
import { createRequire } from "module";
import { default as react } from "@vitejs/plugin-react";

// ../cms-js-internal/dist/types-BoToPcXg.js
import path from "path";
import { createHash } from "crypto";
import fs, { readFileSync, existsSync, readdirSync, lstatSync } from "fs";
import { join } from "path/posix";
var COMPONENT_EXTENSIONS = [".jsx", ".tsx", ".js", ".ts"];
var ENTRY_POINTS_PATH = "components/partials/";
var MODULE_FOLDER_PATH = "components/modules/";
function sortKeys(input, options = {}) {
  const { deep, compare } = options;
  const cache = /* @__PURE__ */ new WeakMap();
  function deepSortArray(array) {
    const resultFromCache = cache.get(array);
    if (resultFromCache !== void 0) {
      return resultFromCache;
    }
    const result = [];
    cache.set(array, result);
    result.push(
      ...array.map((item) => {
        if (Array.isArray(item)) {
          return deepSortArray(item);
        }
        if (isPlainObject(item)) {
          return _sortKeys(item);
        }
        return item;
      })
    );
    return result;
  }
  function _sortKeys(object) {
    const resultFromCache = cache.get(object);
    if (resultFromCache !== void 0) {
      return resultFromCache;
    }
    const result = {};
    const keys = Object.keys(object).sort(compare);
    cache.set(object, result);
    for (const key of keys) {
      const value = object[key];
      let newValue;
      if (deep && Array.isArray(value)) {
        newValue = deepSortArray(value);
      } else {
        newValue = deep && isPlainObject(value) ? _sortKeys(value) : value;
      }
      Object.defineProperty(result, key, {
        ...Object.getOwnPropertyDescriptor(object, key),
        value: newValue
      });
    }
    return result;
  }
  if (Array.isArray(input)) {
    return deep ? deepSortArray(input) : [...input];
  }
  return _sortKeys(input);
}
function isPlainObject(value) {
  if (typeof value !== "object" || value === null) {
    return false;
  }
  const prototype = Object.getPrototypeOf(value);
  return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
}
var badInlineJsChars = /[\u2028\u2029<>/]/g;
var inlineJsEscapeChars = {
  "\u2028": "\\u2028",
  "\u2029": "\\u2029",
  "<": "\\u003C",
  ">": "\\u003E",
  "/": "\\u002F"
};
function escapeChar(unsafeChar) {
  return inlineJsEscapeChars[unsafeChar];
}
function escapeForInlineJS(input) {
  return input.replace(badInlineJsChars, escapeChar);
}
function jsonStringifyAndEscapeForInlineJS(input, { baseIndent = 0, jsonIndent = 2, prettyPrint = true } = {}) {
  const indentString = " ".repeat(baseIndent);
  jsonIndent = prettyPrint ? jsonIndent : void 0;
  let sorted;
  try {
    if (isPlainObject(input) || Array.isArray(input)) {
      sorted = sortKeys(input, { deep: true });
    }
  } catch (e) {
    console.error("Error sorting Island keys", e);
  }
  return escapeForInlineJS(
    JSON.stringify(sorted ?? input, null, jsonIndent)
  ).replace(/\n/gm, `
${indentString}`);
}
var viteRoot;
var viteCommand;
function resolveIslandPlugin(islandsSet) {
  return {
    enforce: "pre",
    name: "resolve-islands",
    configResolved(config) {
      viteRoot = config.root;
      viteCommand = config.command;
    },
    load(id) {
      if (id.endsWith("?island") || id.endsWith("?client")) {
        const [idWithNoParam] = id.split("?");
        const islandModuleImportPath = `${idWithNoParam}?client-entry`;
        const componentExtension = path.extname(idWithNoParam);
        const componentFilenameWithNoExtension = path.basename(
          idWithNoParam,
          componentExtension
        );
        const modulePath = path.relative(viteRoot, idWithNoParam);
        const moduleId = (viteCommand === "serve" ? idWithNoParam : modulePath).concat("?client-entry");
        if (islandsSet) {
          islandsSet.add(moduleId);
        }
        return `
            const moduleId = '${moduleId}';

            const lazyComponent = () => import('${islandModuleImportPath}');
            lazyComponent.moduleName = '${componentFilenameWithNoExtension}';
            lazyComponent.moduleId = moduleId;

            export default lazyComponent;
          `;
      }
      return null;
    }
  };
}
var clientRenderIsland = "import type { RenderableIsland } from '@hubspot/cms-components';\nimport * as cmsComponents from '@hubspot/cms-components';\nimport { ClientRenderContextProvider } from '@hubspot/cms-components';\nimport { Suspense } from 'react';\nimport ReactDOMClient from 'react-dom/client';\n\nconst buildIslandIdentifierPrefix =\n  cmsComponents.buildIslandIdentifierPrefix || ((id) => id);\n\nexport function clientRenderIsland(\n  renderableIsland: RenderableIsland,\n  Component: React.ComponentType<any>\n) {\n  const {\n    island,\n    rootElement,\n    postHydration,\n    pageUrl,\n    islands,\n    basePath,\n    WrapperModule,\n  } = renderableIsland;\n  let reactRoot: any;\n\n  const rootOptions = {\n    // Ensure useId is unique across island roots\n    identifierPrefix: buildIslandIdentifierPrefix(renderableIsland.island.id),\n  };\n\n  let innerComponent = <Component islandId={island.id} {...island.props} />;\n  if (WrapperModule) {\n    innerComponent = <WrapperModule>{innerComponent}</WrapperModule>;\n  }\n\n  const elementsToHydrate = (\n    <Suspense fallback={`client hydrate fail/waiting for ${island.id}`}>\n      <ClientRenderContextProvider\n        pageUrl={pageUrl}\n        islands={islands}\n        onTopLevelHydrationFinish={postHydration}\n        island={island}\n        basePath={basePath}\n      >\n        {innerComponent}\n      </ClientRenderContextProvider>\n    </Suspense>\n  );\n\n  if (island.clientOnly) {\n    reactRoot = ReactDOMClient.createRoot(rootElement, rootOptions);\n    reactRoot.render(elementsToHydrate);\n  } else {\n    reactRoot = ReactDOMClient.hydrateRoot(\n      rootElement,\n      elementsToHydrate,\n      rootOptions\n    );\n  }\n  return reactRoot;\n}\n";
var virtualClientRenderIslandModuleId = "virtual:clientRenderIsland.tsx";
function clientIslandEntryPlugin() {
  return {
    enforce: "pre",
    name: "client-island-entry-plugin",
    resolveId(id) {
      if (id === virtualClientRenderIslandModuleId) {
        return virtualClientRenderIslandModuleId;
      }
      return null;
    },
    load(id) {
      if (id.endsWith("?client-entry")) {
        const [idWithNoParam] = id.split("?");
        return `
            import { clientRenderIsland } from '${virtualClientRenderIslandModuleId}';
            import Component from '${idWithNoParam}';

            export function render(island) {
              return clientRenderIsland(island, Component)
            }

            export default Component;
          `;
      }
      if (id === virtualClientRenderIslandModuleId) {
        return clientRenderIsland;
      }
      return null;
    }
  };
}
var scriptTagToLogServerMessages = (messagesForBrowser, groupLabel, nonceAttribute) => {
  if (!messagesForBrowser) {
    return "";
  }
  const consoleLines = [];
  for (const message of messagesForBrowser) {
    let funcString = "console.log";
    if (message.level === "error") {
      funcString = "console.error";
    }
    if (message.level === "warn") {
      funcString = "console.warn";
    }
    const argString = message.parameters.map((arg) => JSON.stringify(arg)).join(", ");
    consoleLines.push(`  ${funcString}(${argString});`);
  }
  let groupStart = "";
  let groupEnd = "";
  if (groupLabel !== void 0 && groupLabel !== null) {
    groupStart = `
  console.group(${JSON.stringify(groupLabel)});`;
    groupEnd = `  console.groupEnd()
`;
  }
  return `<script ${nonceAttribute}>${groupStart}
${consoleLines.join("\n")}
${groupEnd}</script>
`;
};
var getComponentExtension = (componentPath) => {
  const filteredExtensions = COMPONENT_EXTENSIONS.filter(
    (ext) => componentPath.endsWith(ext)
  );
  if (filteredExtensions.length === 1) {
    return filteredExtensions[0];
  }
  return void 0;
};
var hasComponentExtension = (componentPath) => {
  return !!getComponentExtension(componentPath);
};
var isStorybookStory = (componentPath) => {
  return !!path.basename(componentPath, path.extname(componentPath)).endsWith(".stories");
};
var removeComponentExtension = (componentPath) => {
  const ext = getComponentExtension(componentPath);
  if (ext == null) {
    return componentPath;
  }
  return componentPath.slice(0, -1 * ext.length);
};
function getEntryPointHash(entryPoint) {
  return createHash("md5").update(entryPoint).digest("hex").slice(0, 6);
}
function getEntryPointHashWithIndexSuffix(entryPoint, index) {
  const renderIndexSuffix = index != null ? `i${index}` : "";
  return `${getEntryPointHash(entryPoint)}${renderIndexSuffix}`;
}
function getCMSAssetConfig(webRoot) {
  const cmsAssetsPath = path.join(webRoot, "cms-assets.json");
  const cmsThemePath = path.join(webRoot, "theme.json");
  const configPathToUse = fs.existsSync(cmsAssetsPath) ? cmsAssetsPath : cmsThemePath;
  const parsedConfig = JSON.parse(
    fs.readFileSync(configPathToUse).toString()
  );
  return parsedConfig;
}
var ENABLED_FEATURES_GATE_MAP = {
  "cms:jsr:getServerSideProps": "CMS:JSRenderer:GetServerSideProps",
  "cms:jsr:RemoveCjsPlugin": "CMS:JSRenderer:RemoveCjsPlugin",
  "cms:jsr:analyzeCmsModules": "CMS:JSRenderer:AnalyzeCmsModules"
};
function isUngatedFor(gates, gate) {
  return gates.includes(gate);
}
var findAllComponentsIn = (webRoot, componentsFolder) => {
  const fullComponentsFolderPath = join(webRoot, componentsFolder);
  const componentsByName = {};
  if (!existsSync(fullComponentsFolderPath)) {
    return componentsByName;
  }
  readdirSync(fullComponentsFolderPath).forEach((fileOrFolderName) => {
    const fullPath = join(fullComponentsFolderPath, fileOrFolderName);
    const subdirPath = join(componentsFolder, fileOrFolderName);
    const isDirectory = lstatSync(fullPath).isDirectory();
    if (!isDirectory && hasComponentExtension(fileOrFolderName) && !isStorybookStory(fileOrFolderName)) {
      const subdirPathNoExtension = removeComponentExtension(subdirPath);
      componentsByName[subdirPathNoExtension] = subdirPath;
    } else if (isDirectory) {
      for (const potentialExtension of COMPONENT_EXTENSIONS) {
        const potentialIndexModule = join(
          subdirPath,
          `index${potentialExtension}`
        );
        const fullPotentialPath = join(
          fullPath,
          `index${potentialExtension}`
        );
        if (existsSync(fullPotentialPath)) {
          const moduleIndexPathNoExtension = removeComponentExtension(potentialIndexModule);
          componentsByName[moduleIndexPathNoExtension] = potentialIndexModule;
          break;
        }
      }
    }
  });
  return componentsByName;
};
function findAllModulesInRoot(webRoot) {
  const allModuleComponents = findAllComponentsIn(
    webRoot,
    "./components/modules"
  );
  const moduleNames = Object.keys(allModuleComponents).map(
    (moduleSubpath) => moduleSubpath.replace("components/modules/", "").replace("/index", "")
  );
  const moduleSubpaths = Object.keys(allModuleComponents);
  const moduleExtensions = Object.values(allModuleComponents).map((path22) => {
    if (!path22)
      return "";
    const extension = path22.split(".").pop() || "";
    return extension;
  });
  const moduleNamesWithExtension = Object.values(allModuleComponents).map(
    (path22) => {
      if (!path22)
        return "";
      const file = path22.replace("components/modules/", "");
      return file.includes("/index.") ? file.split("/index.")[0] : file;
    }
  );
  return {
    moduleNames,
    moduleSubpaths,
    moduleNamesWithExtension,
    moduleExtensions
  };
}
function findAllPartialsInRoot(webRoot) {
  const allPartialComponents = findAllComponentsIn(
    webRoot,
    "./components/partials"
  );
  const partialNames = Object.keys(allPartialComponents).map(
    (partialSubpath) => partialSubpath.replace("components/partials/", "").replace("/index", "")
  );
  const partialSubpaths = Object.keys(allPartialComponents);
  return { partialNames, partialSubpaths };
}
function namespaceModulePropsShape(props) {
  const {
    dataQueryResult,
    hublParameters,
    fieldValues: passedFieldValues,
    hublData,
    experimentalHublData,
    moduleName,
    supplementalFieldValues
  } = props;
  const oldPropsShape = { ...props };
  if (oldPropsShape.dataQueryResult) {
    delete oldPropsShape.dataQueryResult;
  }
  if (oldPropsShape.hublParameters) {
    delete oldPropsShape.hublParameters;
  }
  const fieldValues = passedFieldValues || oldPropsShape;
  return {
    ...fieldValues,
    dataQueryResult,
    fieldValues,
    hublParameters,
    hublData,
    experimentalHublData,
    moduleName,
    supplementalFieldValues
  };
}
function setIn(object, nestedKeysArray, value) {
  let curr = object;
  const finalKey = nestedKeysArray.pop();
  for (let index = 0; index < nestedKeysArray.length; index++) {
    const currentKey = nestedKeysArray[index];
    const nextKey = nestedKeysArray[index + 1];
    if (Number.isInteger(nextKey) || !nextKey && Number.isInteger(finalKey)) {
      if (curr[currentKey] === void 0) {
        curr[currentKey] = [];
      }
    }
    if (curr[currentKey] === void 0) {
      curr[currentKey] = {};
    }
    curr = curr[currentKey];
  }
  if (value !== void 0) {
    curr[finalKey] = value;
  }
}

// ../cms-js-internal/dist/index.js
import * as dotProp from "dot-prop";
import * as parser from "@babel/parser";
import _traverse from "@babel/traverse";
import * as t from "@babel/types";
import { jsx } from "react/jsx-runtime";
import stream from "stream";
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
import * as cmsComponents from "@hubspot/cms-components";
import { ServerRenderContext } from "@hubspot/cms-components";
var { setProperty, getProperty, hasProperty } = dotProp;
var serializeIslandDataForInlineScript = (tweakedIslandsArray, perServerRequestData, baseIndent = 0, prettyPrint) => {
  const islandsArrayToSerialize = tweakedIslandsArray.map(
    ({
      id,
      moduleName,
      moduleId,
      props,
      hydrateOn,
      clientOnly,
      priority,
      url: url3,
      sharedStateID,
      supplementalFieldValues,
      wrapperModuleId,
      wrapperUrl,
      resolvedDataDependencies
    }) => {
      const output = {
        id,
        moduleName,
        moduleId,
        hydrateOn,
        clientOnly,
        priority,
        props,
        url: url3
      };
      if (resolvedDataDependencies) {
        output.resolvedDataDependencies = resolvedDataDependencies;
      }
      if (sharedStateID) {
        output.sharedStateID = sharedStateID;
      }
      if (wrapperModuleId) {
        output.wrapperModuleId = wrapperModuleId;
      }
      if (wrapperUrl) {
        output.wrapperUrl = wrapperUrl;
      }
      const filteredSupplementalFieldValues = filterOutUnreadSupplementalFieldValues(
        supplementalFieldValues,
        perServerRequestData.get("supplementalFieldValuesRead")
      );
      if (filteredSupplementalFieldValues) {
        output.supplementalFieldValues = filteredSupplementalFieldValues;
      }
      if (output.clientOnly) {
        output.supplementalFieldValues = supplementalFieldValues;
      }
      return output;
    }
  );
  return jsonStringifyAndEscapeForInlineJS(islandsArrayToSerialize, {
    baseIndent,
    jsonIndent: 2,
    prettyPrint
  });
};
function filterOutUnreadSupplementalFieldValues(supplementalFieldValues, supplementalFieldValuesRead) {
  if (!supplementalFieldValues) {
    return supplementalFieldValues;
  }
  if (!supplementalFieldValuesRead) {
    return supplementalFieldValues;
  }
  const result = {};
  Array.from(supplementalFieldValuesRead).forEach((fieldPath) => {
    if (hasProperty(supplementalFieldValues, fieldPath)) {
      setProperty(
        result,
        fieldPath,
        getProperty(supplementalFieldValues, fieldPath)
      );
    }
  });
  return result;
}
var writeSharedStateToJsGlobal = (islands, perServerRequestData, indent = 0, prettyPrint) => {
  const sharedStateIDs = islands.map((island) => island.sharedStateID).filter((x2) => !!x2);
  if (sharedStateIDs.length > 0) {
    const indentString = " ".repeat(indent);
    const stateByID = {};
    sharedStateIDs.forEach(
      (id) => stateByID[id] = perServerRequestData.get(id)
    );
    const stringifiedState = jsonStringifyAndEscapeForInlineJS(stateByID, {
      prettyPrint,
      jsonIndent: 2
    });
    return `

var newState = ${stringifiedState};
if(window.__hsSSInit) {
  window.__hsSSInit = Object.assign(window.__hsSSInit, newState);
} else {
  window.__hsSSInit = newState;
}`.replace(/\n/gm, `
${indentString}`);
  }
  return "";
};
function getIslandUrls(roots, viteDevServer) {
  return roots.map((island) => {
    const islandModule = viteDevServer.moduleGraph.getModuleById(
      island.moduleId
    );
    if (!islandModule) {
      throw new Error(`Unknown island moduleId: ${island.moduleId}`);
    }
    let wrapperModule;
    if (island.wrapperModuleId) {
      wrapperModule = viteDevServer.moduleGraph.getModuleById(
        island.wrapperModuleId
      );
    }
    const tweakedIsland = {
      ...island,
      url: islandModule.url,
      wrapperUrl: wrapperModule ? wrapperModule.url : void 0
    };
    return tweakedIsland;
  });
}
function getPerServerRequestUrls(perServerRequestData, viteDevServer) {
  if (!perServerRequestData.has("sharedStateIDs")) {
    return new Map(perServerRequestData);
  }
  const perServerRequestDataWithUrls = new Map(
    perServerRequestData
  );
  perServerRequestData.get("sharedStateIDs").forEach((id) => {
    const reducer = perServerRequestData.get(id);
    if (reducer.reducerFuncModuleId) {
      const reducerWithUrl = {
        ...reducer,
        reducerFuncModuleUrl: viteDevServer.moduleGraph.getModuleById(
          reducer.reducerFuncModuleId
        ).url
      };
      perServerRequestDataWithUrls.set(id, reducerWithUrl);
    }
  });
  return perServerRequestDataWithUrls;
}
var createIslandsGlobalJsForClientInDev = (roots, perServerRequestData, viteDevServer, indent, prettyPrint) => {
  const islands = getIslandUrls(roots, viteDevServer);
  const perServerRequestDataWithUrls = getPerServerRequestUrls(
    perServerRequestData,
    viteDevServer
  );
  return `${" ".repeat(
    indent
  )}window.__islands = ${serializeIslandDataForInlineScript(
    islands,
    perServerRequestData,
    indent,
    prettyPrint
  )}${writeSharedStateToJsGlobal(
    islands,
    perServerRequestDataWithUrls,
    indent,
    prettyPrint
  )}`;
};
function noncePlaceholderPlugin() {
  const HS_DEPLOYED = process.env.AWS_EXECUTION_ENV != null || process.env.HS_DEPLOYED === "true";
  return {
    name: "hs-nonce-placeholder",
    enforce: "post",
    apply() {
      return HS_DEPLOYED;
    },
    transformIndexHtml(html) {
      const regex = /<(style|script|link) (.*)>/gi;
      const replacer = (_, p1, p2) => {
        if (p1 === "style" || p1 === "script" || // if link, only nonce for stylesheet
        p1 === "link" && p2.includes('rel="stylesheet"')) {
          const noncePlaceholderValue = p1 === "script" ? "hs-random-nonce" : "hs-random-style-nonce";
          p2 = `nonce="${noncePlaceholderValue}" ${p2}`;
        }
        return `<${p1} ${p2}>`;
      };
      return html.replace(regex, replacer);
    }
  };
}
var traverse = _traverse.default;
var CMS_MODULE_COMPONENT_NAME = "Module";
var DND_AREA_COMPONENT_NAME = "DndArea";
var PLUGIN_NAME = "findCmsModules";
function findCmsModules(buildContentDescriptors = {}) {
  let config;
  return {
    enforce: "pre",
    name: "findCmsModules",
    configResolved(resolvedConfig) {
      config = resolvedConfig;
    },
    transform(code, id) {
      const moduleInfo = this.getModuleInfo(id);
      if (!shouldAnalyzeModule(config, moduleInfo, code))
        return null;
      const contentDescriptors = analyzeSourceCodeUsages(
        this,
        moduleInfo,
        config,
        code
      );
      if (Object.keys(contentDescriptors.dndAreas).length > 0 || Object.keys(contentDescriptors.modules).length > 0) {
        return {
          meta: {
            findCmsModules: contentDescriptors
          }
        };
      }
    },
    buildEnd(error) {
      if (error)
        throw error;
      const entryPoints = getEntryPoints(this, config);
      const entryPointCmsModuleMap = buildEntryPointsCmsModuleMap(
        this,
        entryPoints
      );
      const relativeEntryPointCmsModuleMap = convertEntryPointPathsToRelative(
        config,
        entryPointCmsModuleMap
      );
      const entryPointIslandCmsModuleMap = buildEntryPointIslandsCmsModuleMap(
        this,
        entryPoints
      );
      const relativeEntryPointIslandCmsModuleMap = convertEntryPointIslandPathsToRelative(
        config,
        entryPointIslandCmsModuleMap
      );
      if (Object.keys(relativeEntryPointIslandCmsModuleMap).length > 0) {
        this.error(`
          Error: <Module /> cannot be used within <Island />
          Found invalid usages:
          ${JSON.stringify(relativeEntryPointIslandCmsModuleMap, null, 2)}
          `);
      }
      const modulesWithinModules = filterEntryPointsToModules(
        relativeEntryPointCmsModuleMap
      );
      if (Object.keys(modulesWithinModules).length > 0) {
        this.error(`
          Error: <Module /> can only be used in React Partials
          Found invalid usages:
          ${JSON.stringify(modulesWithinModules, null, 2)}
        `);
      }
      Object.assign(buildContentDescriptors, relativeEntryPointCmsModuleMap);
    }
  };
}
function convertEntryPointPathsToRelative(config, entryPointsCmsModuleMap) {
  const relativeEntries = Object.entries(entryPointsCmsModuleMap).map(
    ([entryPointPath, cmsModules]) => {
      return [toRelativePath(config, entryPointPath), cmsModules];
    }
  );
  return Object.fromEntries(relativeEntries);
}
function convertEntryPointIslandPathsToRelative(config, entryPointsCmsModuleMap) {
  const relativeEntries = Object.entries(entryPointsCmsModuleMap).map(
    ([entryPointPath, islandContentDescriptors]) => {
      const islandCmsModuleUsage = Object.fromEntries(
        Object.entries(islandContentDescriptors).map(
          ([islandPath, contentDescriptors]) => {
            return [
              toRelativePath(config, islandPath).replace("?client-entry", ""),
              contentDescriptors
            ];
          }
        )
      );
      return [toRelativePath(config, entryPointPath), islandCmsModuleUsage];
    }
  );
  return Object.fromEntries(relativeEntries);
}
function toRelativePath(config, path17) {
  return path17.replace(`${config.root}/`, "");
}
function shouldAnalyzeModule(config, moduleInfo, code) {
  const [fileId, __] = moduleInfo.id.split("?");
  const isExternal = config.command !== "serve" && moduleInfo.isExternal;
  return (
    // analyze customer code only
    !isExternal && moduleInfo.id.startsWith(config.root) && // jsx files that contain "Module" / "DndArea"
    (fileId.endsWith(".tsx") || fileId.endsWith(".jsx")) && (code.includes(CMS_MODULE_COMPONENT_NAME) || code.includes(DND_AREA_COMPONENT_NAME))
  );
}
function getEntryPoints(ctx, config) {
  return Array.from(ctx.getModuleIds()).filter((moduleId) => moduleId.startsWith(config.root)).map((moduleId) => ctx.getModuleInfo(moduleId)).filter((moduleInfo) => moduleInfo.isEntry);
}
function buildEntryPointsCmsModuleMap(ctx, entryPoints) {
  const entryPointCmsModuleUsage = {};
  for (const entryPoint of entryPoints) {
    const result = findCmsModuleUsages(ctx, entryPoint.id);
    if (result) {
      entryPointCmsModuleUsage[entryPoint.id] = result;
    }
  }
  return entryPointCmsModuleUsage;
}
function buildEntryPointIslandsCmsModuleMap(ctx, entryPoints) {
  const entryPointIslandsCmsModuleMap = {};
  for (const entryPoint of entryPoints) {
    const result = findIslandCmsModuleUsage(ctx, entryPoint.id);
    if (result) {
      entryPointIslandsCmsModuleMap[entryPoint.id] = result;
    }
  }
  return entryPointIslandsCmsModuleMap;
}
function analyzeSourceCodeUsages(ctx, moduleInfo, config, code) {
  const sourceAst = parser.parse(code, {
    sourceType: "module",
    plugins: ["jsx", "typescript"]
  });
  const contentDescriptors = { modules: {}, dndAreas: {} };
  let moduleComponentLocalImportName = CMS_MODULE_COMPONENT_NAME;
  let dndAreaComponentLocalImportName = DND_AREA_COMPONENT_NAME;
  traverse(sourceAst, {
    ImportDeclaration(path17) {
      if (t.isStringLiteral(path17.node.source, {
        value: "@hubspot/cms-components"
      })) {
        for (const specifier of path17.node.specifiers) {
          if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported, {
            name: CMS_MODULE_COMPONENT_NAME
          })) {
            moduleComponentLocalImportName = specifier.local.name;
          }
          if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported, {
            name: DND_AREA_COMPONENT_NAME
          })) {
            dndAreaComponentLocalImportName = specifier.local.name;
          }
        }
      }
    },
    JSXOpeningElement(path17) {
      if (t.isJSXIdentifier(path17.node.name, {
        name: moduleComponentLocalImportName
      })) {
        let cmsModuleName;
        let cmsModulePath;
        let cmsModuleLabel;
        for (const prop of path17.node.attributes) {
          if (t.isJSXAttribute(prop) && t.isJSXIdentifier(prop.name, { name: "name" }) && t.isStringLiteral(prop.value)) {
            cmsModuleName = prop.value.value;
            continue;
          }
          if (t.isJSXAttribute(prop) && t.isJSXIdentifier(prop.name, { name: "path" }) && t.isStringLiteral(prop.value)) {
            cmsModulePath = prop.value.value;
            continue;
          }
          if (t.isJSXAttribute(prop) && t.isJSXIdentifier(prop.name, { name: "label" }) && t.isStringLiteral(prop.value)) {
            cmsModuleLabel = prop.value.value;
            continue;
          }
          ctx.error(
            new Error(
              `Error: ${moduleInfo.id.replace(config.root, "")}:${prop.loc.start.line} "name" and "path" must be primitive strings`
            )
          );
        }
        const cmsModuleProps = {
          name: cmsModuleName,
          path: cmsModulePath
        };
        if (cmsModuleLabel) {
          cmsModuleProps.label = cmsModuleLabel;
        }
        if (Object.hasOwn(contentDescriptors.modules, cmsModuleProps.name)) {
          ctx.error(
            new Error(
              `Error: multiple <${CMS_MODULE_COMPONENT_NAME} /> with duplicate name: ${cmsModuleProps.name}`
            )
          );
        }
        contentDescriptors.modules[cmsModuleProps.name] = cmsModuleProps;
      }
      if (t.isJSXIdentifier(path17.node.name, {
        name: dndAreaComponentLocalImportName
      })) {
        let dndAreaName;
        for (const prop of path17.node.attributes) {
          if (t.isJSXAttribute(prop) && t.isJSXIdentifier(prop.name, { name: "name" }) && t.isStringLiteral(prop.value)) {
            dndAreaName = prop.value.value;
            continue;
          }
          ctx.error(
            new Error(
              `Error: ${moduleInfo.id.replace(config.root, "")}:${prop.loc.start.line} "name" must a primitive string`
            )
          );
        }
        const dndArea = {
          name: dndAreaName
        };
        if (Object.hasOwn(contentDescriptors.dndAreas, dndArea.name)) {
          ctx.error(
            new Error(
              `Error: multiple <${DND_AREA_COMPONENT_NAME} /> with duplicate name: ${dndArea.name}`
            )
          );
        }
        contentDescriptors.dndAreas[dndArea.name] = dndArea;
      }
    }
  });
  return contentDescriptors;
}
function findCmsModuleUsages(ctx, moduleId, processed = /* @__PURE__ */ new Set(), result = {}) {
  if (Object.hasOwn(result, moduleId)) {
    return result[moduleId];
  }
  const moduleInfo = ctx.getModuleInfo(moduleId);
  let entryPointContentDescriptors = null;
  if (Object.hasOwn(moduleInfo.meta, PLUGIN_NAME)) {
    entryPointContentDescriptors = {
      ...entryPointContentDescriptors,
      ...moduleInfo.meta[PLUGIN_NAME]
    };
  }
  for (const importedId of [
    ...moduleInfo.importedIds,
    ...moduleInfo.dynamicallyImportedIds
  ]) {
    if (processed.has(importedId)) {
      continue;
    }
    const importedResult = findCmsModuleUsages(
      ctx,
      importedId,
      processed,
      result
    );
    if (importedResult) {
      entryPointContentDescriptors = {
        ...entryPointContentDescriptors,
        ...importedResult
      };
    }
  }
  if (entryPointContentDescriptors) {
    result[moduleId] = entryPointContentDescriptors;
  }
  processed.add(moduleId);
  return entryPointContentDescriptors;
}
function findIslandCmsModuleUsage(ctx, moduleId, processedIslands = /* @__PURE__ */ new Set(), islandModuleResults = {}, processed = /* @__PURE__ */ new Set(), results = {}) {
  processedIslands.add(moduleId);
  if (Object.hasOwn(islandModuleResults, moduleId)) {
    return islandModuleResults[moduleId];
  }
  const moduleInfo = ctx.getModuleInfo(moduleId);
  let resultForModuleId = {};
  if (moduleInfo.id.endsWith("?client-entry")) {
    const mergedDataDependencies = findCmsModuleUsages(
      ctx,
      moduleInfo.id,
      processed,
      results
    );
    if (mergedDataDependencies) {
      resultForModuleId[moduleInfo.id] = mergedDataDependencies;
    }
  }
  for (const importedId of [
    ...moduleInfo.importedIds,
    ...moduleInfo.dynamicallyImportedIds
  ]) {
    if (processedIslands.has(importedId)) {
      continue;
    }
    const importerCmsModuleUsageResult = findIslandCmsModuleUsage(
      ctx,
      importedId,
      processedIslands,
      islandModuleResults,
      processed,
      results
    );
    if (importerCmsModuleUsageResult) {
      resultForModuleId = {
        ...resultForModuleId,
        ...importerCmsModuleUsageResult
      };
    }
  }
  if (Object.keys(resultForModuleId).length > 0) {
    islandModuleResults[moduleId] = resultForModuleId;
    return resultForModuleId;
  }
  return null;
}
function filterEntryPointsToModules(entryPointCmsModuleMap) {
  return Object.fromEntries(
    Object.entries(entryPointCmsModuleMap).filter(
      ([entryPoint]) => entryPoint.startsWith("components/modules/")
    )
  );
}
var promiseForNewWritableStream = () => {
  const chunks = [];
  const writableStream = new stream.Writable();
  writableStream._write = (chunk, encoding, done) => {
    chunks.push(Buffer.from(chunk));
    done();
  };
  const streamDonePromise = new Promise((resolve2, reject) => {
    writableStream.on("error", (error) => {
      reject(error);
    });
    writableStream._final = (done) => {
      resolve2(Buffer.concat(chunks).toString("utf8"));
      done();
    };
  });
  return { streamDonePromise, writableStream };
};
var renderStreamToPromise = async (reactElements, options) => {
  const { streamDonePromise, writableStream } = promiseForNewWritableStream();
  const {
    pipe
    /* abort */
  } = renderToPipeableStream(reactElements, {
    ...options || {},
    onShellReady() {
    },
    onAllReady() {
      pipe(writableStream);
      if (options == null ? void 0 : options.onAllReady) {
        options.onAllReady();
      }
    }
  });
  return streamDonePromise;
};
var {
  createServerRenderContextV2: createServerRenderContextV22,
  createServerRenderContext: createServerRenderContext2,
  renderServerSidePropsWithAsyncLocalStoreContext
} = cmsComponents;
var bootStrapRenderContext = () => {
  const renderContext = createServerRenderContextV22 ? createServerRenderContextV22(null, {
    environmentConfig: null,
    entryPointBasePath: "",
    supplementalFieldValues: {},
    messagesForBrowser: []
  }) : createServerRenderContext2("", null);
  return renderContext;
};
async function renderOnServer(elements, renderContext = bootStrapRenderContext(), debugName, renderOptions) {
  let html = await renderStreamToPromise(
    /* @__PURE__ */ jsx(ServerRenderContext.Provider, { value: renderContext, children: elements }),
    renderOptions
  );
  if (renderContext.messagesForBrowser.length > 0) {
    html = `${html}${scriptTagToLogServerMessages(
      renderContext.messagesForBrowser,
      `Server messages rendering: ${debugName}`
    )}`;
  }
  return { html, renderContext };
}
function getServerGlobalsToInject(environmentConfig, hsServerPageUrl, hsBasePath, prettyPrint, criticalDevErrors, includeNonces) {
  if (prettyPrint === void 0 && hsServerPageUrl && cmsComponents.isDebugUrlString) {
    prettyPrint = cmsComponents.isDebugUrlString(hsServerPageUrl);
  }
  const serializedJson = jsonStringifyAndEscapeForInlineJS(
    environmentConfig.toJSON(),
    { baseIndent: 6, prettyPrint }
  );
  const globals = [`window.__hsEnvConfig = ${serializedJson};`];
  if (hsServerPageUrl) {
    globals.push(
      `window.__hsServerPageUrl = ${jsonStringifyAndEscapeForInlineJS(
        hsServerPageUrl
      )};`
    );
  }
  if (hsBasePath) {
    globals.push(
      `window.__hsBasePath = ${jsonStringifyAndEscapeForInlineJS(hsBasePath)};`
    );
  }
  if (!environmentConfig.getIsDeployed() && (criticalDevErrors == null ? void 0 : criticalDevErrors.length)) {
    const firstCriticalDevError = criticalDevErrors[0];
    globals.push(`
      customElements.whenDefined('vite-error-overlay').then(() => {
        const ErrorOverlay = customElements.get('vite-error-overlay');
        const error = new Error(${jsonStringifyAndEscapeForInlineJS(
      firstCriticalDevError.message
    )});
        const overlay = new ErrorOverlay(error);

        document.body.appendChild(overlay);
      })
    `);
  }
  const nonceAttr = includeNonces && cmsComponents.SCRIPT_NONCE_PLACEHOLDER ? ` nonce="${cmsComponents.SCRIPT_NONCE_PLACEHOLDER}"` : "";
  return `
    <script type="text/javascript"${nonceAttr}>
      ${globals.join("\n      ")}
    </script>
      `;
}

// src/createViteDevServer.ts
import { default as mkcert } from "vite-plugin-mkcert";
import { viteCommonjs } from "@originjs/vite-plugin-commonjs";

// src/plugins/devSecretsPlugin.ts
function devSecretsPlugin(secretNames = []) {
  return {
    name: "dev-secrets",
    config: () => {
      return {
        define: {
          "import.meta.env.secretNames": secretNames
        }
      };
    }
  };
}

// src/plugins/cmsComponentsShimPlugin.ts
function cmsComponentsShimPlugin() {
  return {
    name: "cms-components-shim",
    resolveId(id) {
      if (id === "@hubspot/cms-components" || id.startsWith("@hubspot/cms-components/")) {
        return `\0${id}`;
      }
      return null;
    },
    load(id) {
      if (id === "\0@hubspot/cms-components") {
        return `
          export const HSEnvironment = {};
          export const Hublet = {};
          export const createEmptyServerRenderContext = () => ({});
          export const buildStaticEnvConfig = () => ({});
          export const initConfigSingletonFromJSON = () => ({});
          export default {};
        `;
      }
      if (id === "\0@hubspot/cms-components/config") {
        return `
          export const EnvironmentConfig = {};
          export const initConfigSingletonFromJSON = () => ({});
          export default {};
        `;
      }
      if (id === "\0@hubspot/cms-components/fields") {
        return `
          export const Field = {};
          export const traverseFieldsJSON = () => ({});
          export default {};
        `;
      }
      if (id.startsWith("\0@hubspot/cms-components/")) {
        return "export default {};";
      }
      return null;
    }
  };
}

// src/plugins/hsStaticAssetPlugin.ts
import { createProxyMiddleware } from "http-proxy-middleware";
function hsStaticAssetPlugin() {
  return {
    name: "hsstatic-assets-plugin",
    enforce: "pre",
    configureServer(server) {
      return () => {
        const getDomainInfo = (req) => {
          const { authedPortalId, authedHublet, sslEnabled, authedEnv } = req.app.locals;
          const env2 = authedEnv === "qa" ? "qa" : "";
          const previewDomain = `${authedPortalId}.hubspotpreview${env2}-${authedHublet}.com`;
          const protocol = sslEnabled ? "https" : "http";
          return { previewDomain, protocol };
        };
        server.middlewares.use(
          createProxyMiddleware(
            (__pathname, req) => {
              var _a;
              if (!((_a = req.url) == null ? void 0 : _a.match("^/hs/hsstatic/.*")))
                return false;
              const { authedPortalId, authedHublet, authedEnv } = req.app.locals;
              return !!(authedPortalId && authedHublet && authedEnv);
            },
            {
              changeOrigin: true,
              secure: false,
              xfwd: true,
              logLevel: "silent",
              // This is a placeholder target that gets overridden by the router
              // but is a required parameter for initialization
              target: "https://hubspot.com",
              router: (req) => {
                const { previewDomain, protocol } = getDomainInfo(req);
                return `${protocol}://${previewDomain}`;
              },
              onProxyReq: (proxyReq, req, __res) => {
                const { previewDomain, protocol } = getDomainInfo(req);
                proxyReq.setHeader("X-Forwarded-Proto", protocol);
                proxyReq.setHeader("host", previewDomain);
                proxyReq.setHeader(
                  "referer",
                  `${protocol}://${previewDomain}/content-rendering/v1/public/_hcms/preview/template/multi`
                );
              }
            }
          )
        );
      };
    }
  };
}

// src/createViteDevServer.ts
import { readFileSync as readFileSync2 } from "fs";
import { join as join2 } from "path";
function getPackageJson(packagePath2) {
  return JSON.parse(readFileSync2(join2(packagePath2, "package.json")).toString());
}
function getDepsForPackage(packagePath2) {
  const packageJson = getPackageJson(packagePath2);
  return packageJson.dependencies ? Object.keys(packageJson.dependencies) : [];
}
function getDepsForPackageIfExists(packagePath2) {
  try {
    return getDepsForPackage(packagePath2);
  } catch (e) {
    console.log("No package.json at ", packagePath2);
    return [];
  }
}
async function createViteDevServer(webRoot, port, sslEnabled, domainsToProxy = [], jsRenderingGates, secretNames) {
  const additionalMkcertHosts = domainsToProxy.map((proxyDomain) => [
    `${proxyDomain}.localhost`,
    `${proxyDomain}.hslocal.net`
  ]).flat();
  if (process.env.VITE_ORIGIN) {
    console.log(`
Custom origin: ${process.env.VITE_ORIGIN}
`);
  }
  const origin = process.env.VITE_ORIGIN ?? (sslEnabled ? `https://hslocal.net:${port}` : `http://hslocal.net:${port}`);
  const consumerDeps = getDepsForPackageIfExists(webRoot);
  const isProjectWithReact = consumerDeps.includes("@hubspot/cms-components") || process.env.TRANSLATE_ASSET;
  const componentsShimPlugin = isProjectWithReact ? null : cmsComponentsShimPlugin();
  const ssrAndOptimizeDep = isProjectWithReact ? {
    ssr: {
      // TODO: might need more entries here to get things to resolve through
      // resolveWebRootDepsPlugin
      noExternal: "@hubspot/cms-components"
    },
    resolve: {
      conditions: ["server"],
      dedupe: [
        "react",
        "react-dom",
        "@hubspot/cms-components",
        "styled-jsx"
      ]
    },
    optimizeDeps: {
      include: ["react", "react-dom", "react-dom/client"]
    }
  } : {};
  const require2 = createRequire(import.meta.url);
  const reactAndIslandsPlugins = isProjectWithReact || process.env.VITEST ? [
    react({
      babel: {
        plugins: [
          require2.resolve("babel-plugin-styled-components"),
          require2.resolve("styled-jsx/babel"),
          require2.resolve("babel-plugin-macros")
        ]
      }
    }),
    clientIslandEntryPlugin(),
    resolveIslandPlugin(),
    jsRenderingGates.includes("CMS:JSRenderer:RemoveCjsPlugin") ? null : viteCommonjs(),
    devSecretsPlugin(secretNames),
    noncePlaceholderPlugin()
  ] : [];
  const viteConfig = {
    appType: "custom",
    server: {
      middlewareMode: true,
      host: "hslocal.net",
      origin,
      hmr: {
        protocol: sslEnabled ? "wss" : void 0
      }
    },
    root: webRoot,
    ...ssrAndOptimizeDep,
    plugins: [
      hsStaticAssetPlugin(),
      jsRenderingGates.includes("CMS:JSRenderer:AnalyzeCmsModules") ? findCmsModules() : null,
      sslEnabled ? mkcert({ hosts: additionalMkcertHosts }) : null,
      componentsShimPlugin,
      ...reactAndIslandsPlugins
    ],
    css: {
      postcss: webRoot
    },
    envDir: webRoot,
    envPrefix: "HS_",
    define: {
      "process.env": {}
    }
  };
  return createViteServer(viteConfig);
}
var createViteDevServer_default = createViteDevServer;

// src/createDevServer.ts
import path16 from "path";
import fs7 from "fs";
import url2 from "url";
import express2 from "express";
import http3 from "http";
import bodyParser from "body-parser";
import { spawn as spawn2 } from "child_process";
import { normalizePath as normalizePath10 } from "vite";

// src/routes/createDevServerRoutes.ts
import {
  Router as Router2,
  urlencoded,
  static as expressStatic
} from "express";
import { createProxyMiddleware as createProxyMiddleware2 } from "http-proxy-middleware";

// src/routes/partial.ts
import path7 from "path";
import { normalizePath as normalizePath5 } from "vite";

// src/lib/fullOriginalUrlFromRequest.ts
function fullOriginalUrlFromRequest(request) {
  return `${request.protocol}://${request.get("host")}${request.originalUrl}`;
}

// src/lib/renderPartial.ts
import { join as joinPosix } from "path/posix";

// src/lib/renderComponentWithCSS.ts
import {
  renderToStaticMarkup as renderToStaticMarkup2
} from "react-dom/server";

// src/lib/packagePath.ts
import path2 from "path";
import url from "url";
import { normalizePath } from "vite";
function packagePath(metaUrl, projectPath) {
  if (true) {
    return normalizePath(
      path2.resolve(path2.dirname(url.fileURLToPath(metaUrl)), projectPath)
    );
  }
  const parentDirPath = normalizePath(path2.dirname(url.fileURLToPath(metaUrl)));
  const subPath = parentDirPath.replace(/^.+cms-dev-server\/src\//, "");
  const subPathParentDirs = subPath.split("/").map(() => "..");
  return path2.resolve(
    path2.dirname(url.fileURLToPath(metaUrl)),
    path2.join(...subPathParentDirs, projectPath)
  );
}

// src/lib/moduleGraph.ts
var findFullPathInModuleGraph = (modulePathNoExtension, moduleGraph) => {
  for (const extension of COMPONENT_EXTENSIONS) {
    const pathToTry = `${modulePathNoExtension}${extension}`;
    if (moduleGraph.fileToModulesMap.has(pathToTry)) {
      return pathToTry;
    }
  }
};

// src/lib/pathHelpers.ts
var getComponentPaths = (viteServer, componentPath) => {
  let componentPathWithExtension;
  let componentPathNoExtension;
  if (hasComponentExtension(componentPath)) {
    componentPathWithExtension = componentPath;
    componentPathNoExtension = removeComponentExtension(componentPath);
  } else {
    componentPathNoExtension = componentPath;
  }
  if (!componentPathWithExtension) {
    componentPathWithExtension = findFullPathInModuleGraph(
      componentPathNoExtension,
      viteServer.moduleGraph
    );
    if (!componentPathWithExtension) {
      throw new Error(
        `Couldn't find full path to component: ${componentPathNoExtension}`
      );
    }
  }
  return [componentPathNoExtension, componentPathWithExtension];
};
var getEntryPointBasePath = (componentPath) => {
  if (componentPath.includes(ENTRY_POINTS_PATH)) {
    return `partial/${componentPath.split(ENTRY_POINTS_PATH)[1]}`;
  }
  if (componentPath.includes(MODULE_FOLDER_PATH)) {
    return `module/${componentPath.split(MODULE_FOLDER_PATH)[1]}`;
  }
  throw new Error("Unknown entry point path type");
};

// src/lib/renderComponentWithCSS.ts
async function renderComponentWithCSS(viteServer, componentPath, Component, propsAndExtraDeps, pageUrl, entryPointBasePath, contextOptions, environmentConfig, renderOptions, getServerSideProps, modifyHtmlCallback) {
  const internalSsrPath = packagePath(import.meta.url, "internalSsr");
  const { renderComponentOnServer, collectCssInDev: collectCssInDev2 } = await viteServer.ssrLoadModule(internalSsrPath);
  const [, componentPathWithExtension] = getComponentPaths(
    viteServer,
    componentPath
  );
  const renderResult = await renderComponentOnServer(
    Component,
    propsAndExtraDeps,
    pageUrl,
    environmentConfig,
    entryPointBasePath,
    contextOptions,
    renderOptions,
    getServerSideProps
  );
  let html = renderResult.html;
  const renderContext = renderResult.renderContext;
  if (modifyHtmlCallback) {
    html = modifyHtmlCallback(
      html,
      renderContext,
      []
      // Build-time generated static asset array is only available when deployed
    );
  }
  const cssNeeded = collectCssInDev2(componentPathWithExtension, viteServer);
  let inlineAssets = [];
  if (renderContext.inlineAssets && Array.isArray(renderContext.inlineAssets)) {
    inlineAssets = renderContext.inlineAssets.map(
      ({ render: staticAssetRenderFunc, ...staticAsset }) => ({
        ...staticAsset,
        html: renderToStaticMarkup2(staticAssetRenderFunc())
      })
    );
  }
  return { html, inlineAssets, cssNeeded, renderContext };
}
var renderComponentWithCSS_default = renderComponentWithCSS;

// src/lib/renderHelpers.ts
function getByteSizeOf(props) {
  return Buffer.from(JSON.stringify(props)).length;
}
function formatBytesToString(bytes) {
  if (bytes > 1e6) {
    return ["\x1B[31m", `${(bytes / 1e6).toFixed(2)}mb`, `\x1B[0m`];
  } else if (bytes > 1e4) {
    return ["\x1B[33m", `${(bytes / 1e3).toFixed(2)}kb`, `\x1B[0m`];
  } else {
    return ["\x1B[32m", `${(bytes / 1e3).toFixed(2)}kb`, `\x1B[0m`];
  }
}
var getPropsInfo = (props, reportOptions = { showNestedKeySizeIfGreater: null }, recursionDepth = 0) => {
  if (recursionDepth > 8) {
    return [];
  }
  const propsSizeInBytes = getByteSizeOf(props);
  const result = formatBytesToString(propsSizeInBytes);
  if (!Array.isArray(props) && Object.keys(props).length > 0 && reportOptions.showNestedKeySizeIfGreater != null && propsSizeInBytes > reportOptions.showNestedKeySizeIfGreater) {
    for (const [key, value] of Object.entries(props)) {
      const size = getPropsInfo(value, reportOptions, recursionDepth + 1);
      if (Array.isArray(value)) {
        result.push("\n", `${key}[${value.length}]`, ...size);
      } else {
        result.push("\n", key, ...size);
      }
    }
  }
  return result.flat();
};
var logPartialInfo = (partialPath, props) => {
  console.log("Rendering partial", partialPath);
  console.group();
  console.log(
    "Props size: ",
    ...getPropsInfo(props, { showNestedKeySizeIfGreater: 1e6 })
  );
  console.groupEnd();
};

// src/lib/renderPartial.ts
var lookForModuleInFolder = async (modulePath, viteServer) => {
  let componentModule;
  const insideFolderPath = joinPosix(modulePath, "index");
  try {
    componentModule = await viteServer.ssrLoadModule(insideFolderPath);
  } catch (e) {
    if (!e.message.includes("Failed to load url")) {
      throw e;
    }
  }
  return [componentModule, insideFolderPath];
};
async function renderPartial(viteServer, partialPath, props, pageUrl, basePath, environmentConfig, renderOptions) {
  try {
    logPartialInfo(partialPath, props);
  } catch (e) {
    console.log("unable to log partial prop info");
    console.error(e);
  }
  let componentModule;
  let resolvedPath;
  if (!hasComponentExtension(partialPath)) {
    [componentModule, resolvedPath] = await lookForModuleInFolder(
      partialPath,
      viteServer
    );
  }
  if (!componentModule) {
    componentModule = await viteServer.ssrLoadModule(partialPath);
    resolvedPath = componentModule ? partialPath : void 0;
  }
  if (!componentModule) {
    throw new Error(`Couldn't find partial: ${partialPath}`);
  }
  const Component = componentModule.default;
  if (!Component) {
    throw new Error(`Couldn't find default export on partial: ${resolvedPath}`);
  }
  return renderComponentWithCSS_default(
    viteServer,
    resolvedPath,
    Component,
    { props },
    pageUrl,
    basePath,
    void 0,
    // contextOptions
    environmentConfig,
    renderOptions
  );
}
var renderPartial_default = renderPartial;

// src/lib/templates.ts
import { promises as fsPromises } from "fs";
import {
  isDebugUrlString as isDebugUrlString2
} from "@hubspot/cms-components";

// src/lib/criticalDevErrorsToServerMessages.ts
var criticalDevErrorsToServerMessages = (criticalDevErrors) => {
  const logMessages = criticalDevErrors.map(
    (criticalDevError) => {
      return {
        level: criticalDevError.level,
        parameters: [criticalDevError.message]
      };
    }
  );
  return logMessages;
};
var criticalDevErrorsToServerMessages_default = criticalDevErrorsToServerMessages;

// src/lib/templates.ts
var { readFile } = fsPromises;
var generateIslandSetupScriptBlock = () => {
  return `
    <script type="module">
      import { initConfigSingletonFromJSON } from '@hubspot/cms-components/config';
      initConfigSingletonFromJSON(window.__hsEnvConfig);
      </script>
      <script type="module">
      import { setupIslandHydration } from '${packagePath(
    import.meta.url,
    "island-runtime"
  )}';
      setupIslandHydration();
    </script>
      `;
};
var createdPlainHtmlTemplate = async (baseTemplatePath, title, globalScriptBlock) => {
  const htmlTemplateBase = await readFile(baseTemplatePath, "utf-8");
  return htmlTemplateBase.replace("<!--title-->", title).replace(
    "<!--bodyend-->",
    `
  ${globalScriptBlock}
  <!--bodyend-->`
  );
};
var createIslandHtmlTemplate = async (baseTemplatePath, title, globalScriptBlock) => {
  let htmlTemplate = await createdPlainHtmlTemplate(
    baseTemplatePath,
    title,
    globalScriptBlock
  );
  htmlTemplate = htmlTemplate.replace(
    "<!--bodyend-->",
    `
    ${generateIslandSetupScriptBlock()}
    <!-- ISLAND_RUNTIME_AND_SETUP_SCRIPT_BLOCK -->
  <!--islandsglobal-->
  `
  );
  return htmlTemplate;
};
var createHtmlShellDependingOnRenderContext = async (baseTemplatePath, url3, title, renderContext, viteServer, jsRenderingGates) => {
  let htmlTemplate;
  const prettyPrint = isDebugUrlString2(url3);
  const serverMessages = criticalDevErrorsToServerMessages_default(
    renderContext.criticalDevErrors
  );
  const serverLogScript = serverMessages.length ? scriptTagToLogServerMessages(
    serverMessages,
    "@hubspot/cms-dev-server messages"
  ) : "";
  if (renderContext.islands.length) {
    const globalScriptBlock = getServerGlobalsToInject(
      renderContext.environmentConfig,
      renderContext.pageUrl,
      renderContext.entryPointBasePath,
      void 0,
      renderContext.criticalDevErrors
    );
    htmlTemplate = await createIslandHtmlTemplate(
      baseTemplatePath,
      title,
      `${globalScriptBlock}${serverLogScript}`
    );
    htmlTemplate = htmlTemplate.replace(
      "<!--islandsglobal-->",
      `<script>
        ${createIslandsGlobalJsForClientInDev(
        renderContext.islands,
        renderContext.perServerRequestData,
        viteServer,
        6,
        prettyPrint
      )}
    </script>
  `
    );
  } else {
    const globalScriptBlock = getServerGlobalsToInject(
      renderContext.environmentConfig,
      void 0,
      void 0,
      void 0,
      renderContext.criticalDevErrors
    );
    htmlTemplate = await createdPlainHtmlTemplate(
      baseTemplatePath,
      title,
      `${globalScriptBlock}${serverLogScript}`
    );
  }
  return viteServer.transformIndexHtml(url3, htmlTemplate);
};
var getIslandRuntimeAndGlobalToInject = async (sortedIslandRoots, perServerRequestData, viteServer, gates, prettyPrint) => {
  const internalSsrPath = packagePath(import.meta.url, "internalSsr");
  const { createIslandsGlobalJsForClientInDev: createIslandsGlobalJsForClientInDev2 } = await viteServer.ssrLoadModule(internalSsrPath);
  const islandRuntimeScript = await viteServer.transformIndexHtml(
    "/",
    generateIslandSetupScriptBlock()
  );
  return `${islandRuntimeScript}
    <script>${createIslandsGlobalJsForClientInDev2(
    sortedIslandRoots,
    perServerRequestData,
    viteServer,
    4,
    prettyPrint
  )}</script>
    `;
};

// src/routes/partial.ts
import { buildStaticEnvConfig as buildStaticEnvConfig3 } from "@hubspot/cms-components";

// src/lib/trackUsage.ts
import { http as hsCliHttp } from "@hubspot/local-dev-lib/http";
import { getConfigAccountIfExists } from "@hubspot/local-dev-lib/config";
import axios from "axios";
import { getAxiosConfig } from "@hubspot/local-dev-lib/http/getAxiosConfig";

// src/lib/debug.ts
import { default as debugFactory } from "debug";
var debug = debugFactory("cms-dev-server");

// src/lib/logColors.ts
var CONTROL_CHARACTER = "\x1B";
var DEFAULT_SCHEME = "[0m";
var ForeGroudANSIColorMap = {
  black: 30,
  red: 31,
  green: 32,
  yellow: 33,
  blue: 34,
  magenta: 35,
  cyan: 36,
  white: 37
};
function wrapMessageInColor(color, message) {
  return `${CONTROL_CHARACTER}[${ForeGroudANSIColorMap[color]}m${message}${CONTROL_CHARACTER}${DEFAULT_SCHEME}`;
}

// src/lib/trackUsage.ts
var DEV_SERVER_USAGE_ENDPOINT_AUTHENTICATED = "/cms-dev-server-usage/v1/authenticated";
var DEV_SERVER_USAGE_ENDPOINT = "/cms-dev-server-usage/v1";
var EVENT_NAME = "dev-server-interaction";
var trackingAccountId = null;
var trackingEnv = null;
var getPlatform = () => {
  switch (process.platform) {
    case "darwin":
      return "macos";
    case "win32":
      return "windows";
    default:
      return process.platform;
  }
};
var getNodeVersionData = () => process.version;
function trackUsage(action) {
  const accountConfig = trackingAccountId && getConfigAccountIfExists(trackingAccountId);
  const isAuthedWithPersonalAccessKey = accountConfig && accountConfig.authType === "personalaccesskey";
  const usageEvent = {
    portalId: trackingAccountId,
    eventClass: "INTERACTION" /* INTERACTION */,
    eventName: EVENT_NAME,
    action,
    nodeVersion: getNodeVersionData(),
    version: "1.2.27",
    os: getPlatform()
  };
  const url3 = isAuthedWithPersonalAccessKey ? DEV_SERVER_USAGE_ENDPOINT_AUTHENTICATED : DEV_SERVER_USAGE_ENDPOINT;
  const baseRequestOptions = {
    url: url3,
    data: usageEvent
  };
  if (isAuthedWithPersonalAccessKey) {
    return hsCliHttp.post(trackingAccountId, baseRequestOptions);
  }
  const config = getAxiosConfig({
    ...baseRequestOptions,
    env: trackingEnv,
    method: "POST"
  });
  return axios(config);
}
var setTrackingInfo = (accountId, env2) => {
  trackingAccountId = accountId;
  trackingEnv = env2;
};
function sendTrackingRequest(action) {
  setImmediate(async () => {
    try {
      await trackUsage(action);
      debug(
        wrapMessageInColor(
          "white",
          `Sent usage tracking action event: ${action}`
        )
      );
    } catch (e) {
      debug(wrapMessageInColor("red", `Usage tracking failed: ${e.message}`));
    }
  });
}

// src/lib/renderModulePreview.ts
import { buildStaticEnvConfig as buildStaticEnvConfig2 } from "@hubspot/cms-components";
import path6 from "path";
import { normalizePath as normalizePath4 } from "vite";

// src/lib/proxyHelpers.ts
import fs2 from "fs";
import { resolve } from "path";
import { unescape } from "html-escaper";
var localJsRenderStartString = '<!-- proxy local render of "';
var localJsRenderEndString = "end proxy local render -->";
function isRecord(value) {
  return typeof value === "object" && value !== null;
}
var findLocalRenderPlaceholders = (body) => {
  let offsetSoFar = 0;
  const result = [];
  while (offsetSoFar < body.length && offsetSoFar !== -1) {
    const startOffset = body.indexOf(localJsRenderStartString, offsetSoFar);
    offsetSoFar = startOffset;
    if (startOffset >= 0) {
      const nextNewlineOffset = body.indexOf(
        "\n",
        startOffset + localJsRenderStartString.length
      );
      const pathEndOffset = body.indexOf(
        '"',
        startOffset + localJsRenderStartString.length
      );
      const nearestNewlineOrQuoteAfterBlockOpen = Math.min(
        nextNewlineOffset,
        pathEndOffset
      );
      offsetSoFar = nearestNewlineOrQuoteAfterBlockOpen;
      if (pathEndOffset >= 0 && pathEndOffset < nextNewlineOffset) {
        const path17 = body.substring(
          startOffset + localJsRenderStartString.length,
          pathEndOffset
        );
        offsetSoFar = pathEndOffset + 1;
        if (startOffset >= 0 && path17) {
          const nextCommentEndOffset = body.indexOf("-->", pathEndOffset);
          const endOffset = body.indexOf(localJsRenderEndString, pathEndOffset);
          offsetSoFar = Math.min(nextCommentEndOffset, endOffset);
          if (endOffset >= startOffset && endOffset < nextCommentEndOffset) {
            const jsonString = body.substring(pathEndOffset + 1, endOffset).trim();
            try {
              let json;
              try {
                json = JSON.parse(unescape(jsonString));
              } catch (e) {
                json = JSON.parse(jsonString);
              }
              if (!isRecord(json.request)) {
                console.error(
                  `Invalid JSON inside <!-- proxy local render .. --> string (missing request key)`
                );
              } else if (!isRecord(json.props)) {
                console.error(
                  `Invalid JSON inside <!-- proxy local render .. --> string (missing props key)`
                );
              } else {
                result.push({
                  startOffset,
                  endOffset: endOffset + localJsRenderEndString.length,
                  path: path17,
                  json
                });
              }
              offsetSoFar = endOffset + localJsRenderEndString.length;
            } catch (e) {
              console.error(
                `Invalid JSON inside <!-- proxy local render .. --> string (around offset ${pathEndOffset})`
              );
              offsetSoFar = endOffset;
            }
          }
        }
      }
    }
  }
  return result;
};
var getHSProjectConfig = (hsProjectConfigPath) => {
  try {
    return JSON.parse(fs2.readFileSync(hsProjectConfigPath, "utf8"));
  } catch (e) {
    console.warn(
      `Missing hsproject.json file (${resolve(hsProjectConfigPath)}): `,
      e.message
    );
    return null;
  }
};
var getProjectNameFromHSConfig = (hsProjectConfigPath) => {
  const hsProjectConfig = getHSProjectConfig(hsProjectConfigPath);
  if (hsProjectConfig) {
    return hsProjectConfig.name;
  }
  return null;
};

// src/proxyPage/proxyPage.ts
import path5 from "path";
import { normalizePath as normalizePath3 } from "vite";
import { getConfigAccountIfExists as getConfigAccountIfExists2 } from "@hubspot/local-dev-lib/config";
import { http as hsCliHttp6 } from "@hubspot/local-dev-lib/http";

// src/lib/renderModule.ts
import { join as joinPosix2 } from "path/posix";
import * as cmsComponents2 from "@hubspot/cms-components";
import { http as hsCliHttp3 } from "@hubspot/local-dev-lib/http";

// src/lib/fetchModuleGraphQLData.ts
import { http as hsCliHttp2 } from "@hubspot/local-dev-lib/http";
var graphQLCache = /* @__PURE__ */ new Map();
async function fetchModuleGraphQLData(accountId, query, requestedModulePath, pageUrl) {
  const { searchParams } = new URL(pageUrl);
  const hsLocalQueryKey = searchParams.get("hsLocalQueryKey");
  const compositeQueryKey = `${hsLocalQueryKey}:${query}`;
  let dataQueryResult;
  if (graphQLCache.has(compositeQueryKey)) {
    console.log(`Using cached GraphQL Query for ${requestedModulePath}`);
    return Promise.resolve(graphQLCache.get(compositeQueryKey));
  }
  try {
    dataQueryResult = (await hsCliHttp2.post(accountId, {
      url: "/collector/v3/graphql",
      data: {
        query
      }
    })).data;
  } catch (e) {
    throw new Error(e);
  }
  graphQLCache.set(compositeQueryKey, dataQueryResult);
  return dataQueryResult;
}

// src/lib/getFieldValuesForModule.ts
import { traverseFieldsJSON } from "@hubspot/cms-components/fields";
function getFieldValuesForModule(fieldsJSON, fieldOverrides = {}) {
  const props = {};
  traverseFieldsJSON(fieldsJSON, fieldOverrides, (fieldPathArray, value) => {
    setIn(props, fieldPathArray, value);
  });
  return props;
}

// src/lib/renderModule.ts
var VALIDATE_FIELDS_ENDPOINT = "/designmanager/v1/modules/validate-fields";
var VALIDATE_META_ENDPOINT = "/designmanager/v1/modules/validate-meta";
var { filterToModuleDataDepsIncludedIn, getModuleDataDependecyTypeFrom } = cmsComponents2;
var handleValidationApiError = (result, type, renderContext, requestedModulePath) => {
  if (result.status === "rejected") {
    const errorMessage = result.reason ? `${result.reason.name}: ${result.reason.message}` : "";
    if (errorMessage) {
      renderContext.criticalDevErrors.push({
        message: `Failed request to validate module for ${requestedModulePath} - ${type} Validation Error`,
        error: new Error(errorMessage),
        level: "error"
      });
    }
  }
};
var handleModuleValidationErrors = (validationErrors = [], type, renderContext, requestedModulePath) => {
  const validationSeverityToLogLevel = {
    FATAL: "error",
    WARNING: "warn"
  };
  if (!Array.isArray(validationErrors)) {
    return;
  }
  validationErrors.forEach((validationError) => {
    renderContext.criticalDevErrors.push({
      message: `${type} Validation Error in ${requestedModulePath}: ${validationError.message}`,
      error: new Error(validationError.message),
      level: validationSeverityToLogLevel[validationError.severity] || "info"
    });
  });
};
var getApplyValidationToRenderContext = (portalId, fieldsJSON, metaJSON, requestedModulePath) => {
  return async (renderResult) => {
    const { renderContext } = renderResult;
    let fieldsValidationResponse;
    let metaValidationResponse;
    try {
      const [fieldsResult, metaResult] = await Promise.allSettled([
        hsCliHttp3.post(portalId, {
          url: VALIDATE_FIELDS_ENDPOINT,
          data: fieldsJSON,
          resolveWithFullResponse: true
        }),
        hsCliHttp3.post(portalId, {
          url: VALIDATE_META_ENDPOINT,
          data: metaJSON,
          resolveWithFullResponse: true
        })
      ]);
      [fieldsResult, metaResult].forEach(
        (result, index) => handleValidationApiError(
          result,
          index === 0 ? "Field" : "Meta",
          renderContext,
          requestedModulePath
        )
      );
      fieldsValidationResponse = fieldsResult.status === "fulfilled" ? fieldsResult.value : null;
      metaValidationResponse = metaResult.status === "fulfilled" ? metaResult.value : null;
    } catch {
      console.log("Failed to validate module for", requestedModulePath);
    }
    [fieldsValidationResponse, metaValidationResponse].forEach(
      (response, index) => {
        handleModuleValidationErrors(
          response,
          index === 0 ? "Field" : "Meta",
          renderContext,
          requestedModulePath
        );
      }
    );
    return renderResult;
  };
};
var lookForModuleInFolder2 = async (modulePath, viteServer) => {
  let componentModule;
  const insideFolderPath = joinPosix2(modulePath, "index");
  try {
    componentModule = await viteServer.ssrLoadModule(insideFolderPath);
  } catch (e) {
    if (!e.message.includes("Failed to load url")) {
      throw e;
    }
  }
  return [componentModule, insideFolderPath];
};
async function renderModule(viteServer, requestedModulePath, moduleProps, pageUrl, basePath, environmentConfig, renderOptions) {
  console.log("Rendering module", requestedModulePath);
  const {
    fieldValues: fieldOverrides = {},
    hublParameters,
    supplementalFieldValues,
    experimentalHublData,
    hublData,
    moduleName
  } = moduleProps;
  const ungatedForServerSideProps = isUngatedFor(
    environmentConfig.getGates(),
    "CMS:JSRenderer:GetServerSideProps"
  );
  const messagesForBrowser = [];
  let componentModule;
  let dataQueryResult;
  let foundPath;
  let getServerSideProps;
  let extraDeps;
  if (!hasComponentExtension(requestedModulePath)) {
    [componentModule, foundPath] = await lookForModuleInFolder2(
      requestedModulePath,
      viteServer
    );
  }
  if (!componentModule) {
    componentModule = await viteServer.ssrLoadModule(requestedModulePath);
    foundPath = componentModule ? requestedModulePath : void 0;
  }
  if (!componentModule) {
    throw new Error(`Couldn't find module: ${requestedModulePath}`);
  }
  const Component = componentModule.Component;
  const fields = componentModule.fields;
  const meta = componentModule.meta;
  if (!Component) {
    throw new Error(
      `Module does not have a named Component export: ${foundPath}`
    );
  } else if (!fields) {
    throw new Error(`Module does not have a named fields export: ${foundPath}`);
  } else if (!meta) {
    throw new Error(`Module does not have a named meta export: ${foundPath}`);
  }
  const internalSsrPath = packagePath(import.meta.url, "internalSsr");
  const { renderFieldsToJson } = await viteServer.ssrLoadModule(internalSsrPath);
  const fieldsJSON = renderFieldsToJson(fields, requestedModulePath);
  const fieldValues = getFieldValuesForModule(fieldsJSON, fieldOverrides);
  const applyFieldsValidationToRenderContext = getApplyValidationToRenderContext(
    environmentConfig.getPortalID(),
    fieldsJSON,
    meta,
    requestedModulePath
  );
  if (componentModule.query && typeof componentModule.query === "string") {
    try {
      dataQueryResult = await fetchModuleGraphQLData(
        environmentConfig.getHubID(),
        componentModule.query,
        requestedModulePath,
        pageUrl
      );
      if (dataQueryResult.errors && dataQueryResult.errors.length) {
        const errorString = `GraphQL query for ${requestedModulePath} had errors.`;
        messagesForBrowser.push({
          level: "error",
          parameters: [errorString]
        });
        dataQueryResult.errors.forEach((graphQLError) => {
          console.error(graphQLError);
          messagesForBrowser.push({
            level: "error",
            parameters: [graphQLError.message, graphQLError]
          });
        });
      }
    } catch (error) {
      const errorString = `Failed to execute query for ${requestedModulePath}.`;
      console.error(errorString);
      console.error(error.message);
      messagesForBrowser.push({
        level: "error",
        parameters: [errorString, error.message]
      });
    }
  }
  const namespacedModuleProps = namespaceModulePropsShape({
    fieldValues,
    hublParameters,
    dataQueryResult,
    supplementalFieldValues,
    experimentalHublData,
    hublData,
    moduleName
  });
  if (ungatedForServerSideProps && componentModule.getServerSideProps) {
    if (!getModuleDataDependecyTypeFrom || !filterToModuleDataDepsIncludedIn) {
      throw new Error(
        `Need to upgrade to @hubspot/cms-components 0.15.x or higher to use getServerSideProps`
      );
    }
    getServerSideProps = componentModule.getServerSideProps;
    const depType = getModuleDataDependecyTypeFrom(
      componentModule.getServerSideProps
    );
    extraDeps = filterToModuleDataDepsIncludedIn(depType, {
      url: new URL(pageUrl),
      contact: void 0,
      // TODO
      request: void 0
      // TODO
    });
  }
  return renderComponentWithCSS_default(
    viteServer,
    foundPath,
    Component,
    { props: namespacedModuleProps, extraDeps },
    pageUrl,
    basePath,
    { supplementalFieldValues, messagesForBrowser },
    environmentConfig,
    renderOptions,
    getServerSideProps,
    componentModule.unstable_modifyHtml
  ).then(applyFieldsValidationToRenderContext);
}
var renderModule_default = renderModule;

// src/proxyPage/utils.ts
import { createEmptyServerRenderContext } from "@hubspot/cms-components";

// src/proxyPage/constants.ts
var VALID_PROXY_DOMAIN_SUFFIXES = ["localhost", "hslocal.net"];

// src/proxyPage/utils.ts
var getSubDomainFromValidLocalDomain = (hostname) => {
  for (const validProxyDomainSuffix of VALID_PROXY_DOMAIN_SUFFIXES) {
    if (hostname.endsWith(`.${validProxyDomainSuffix}`)) {
      return hostname.slice(0, -1 * validProxyDomainSuffix.length - 1);
    }
  }
  return void 0;
};
var randomStringWithLotsOf = (char, maxLength) => {
  return new Array(Math.floor(Math.random() * maxLength)).fill(char).join("");
};
var fakeRenderJsComponent = (indexForThisRender) => {
  return new Promise((resolve2, reject) => {
    const randomTimeout = Math.floor(Math.random() * 200) + indexForThisRender * 1e3;
    setTimeout(() => {
      try {
        const fakeJsRenderedOutput = `<div data-js-rendered>JS render #${indexForThisRender + 1} (${randomTimeout}ms delay) ${randomStringWithLotsOf(
          "?",
          100
        )}</div>
`;
        resolve2({
          html: fakeJsRenderedOutput,
          cssNeeded: "",
          renderContext: createEmptyServerRenderContext(),
          inlineAssets: []
        });
      } catch (e) {
        console.log("Error with JS render...");
        console.error(e);
        reject();
      }
    }, randomTimeout);
  });
};
var consoleWarn = (message) => {
  console.warn("\x1B[33m%s\x1B[0m", "WARNING:", message);
};

// src/proxyPage/renderLocalError.ts
import AnsiToHtmlConverter from "ansi-to-html";
var customColors = [
  // Normal colors
  "#000",
  // black
  "#ec392c",
  // red
  "#b3e439",
  // green
  "#fea525",
  // yellow
  "#76dff3",
  // blue
  "#fd4285",
  // magenta
  "#cfa3ff",
  // cyan
  "#f4f4f4",
  // White
  // Bright colors (mostly identical to ^)
  "#646464",
  "#ec392c",
  "#fea525",
  "#76dff3",
  "#fd4285",
  "#cfa3ff",
  "#f4f4f4"
];
var Converter = new AnsiToHtmlConverter({ colors: customColors });
var darkErrorStyles = `background-color: #222; color: #ccc; padding: 0.5em; font-family: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;`;
var renderLocalError_default = (path17, error) => {
  const stackWithColorClasses = Converter.toHtml(error.stack);
  return `<div data-js-rendered="error" style="${darkErrorStyles}">Error rendering ${path17}<br/><br/><code><pre>${stackWithColorClasses}</pre></code></div>`;
};

// src/proxyPage/fetchPreviewInfo.ts
import { http as hsCliHttp4 } from "@hubspot/local-dev-lib/http";
var fetchPreviewInfo_default = async (accountId, portalId, contentId) => {
  if (!contentId) {
    throw new Error(
      `Invalid contentId when attempting to fetch preview info: ${contentId}`
    );
  }
  try {
    const content = (await hsCliHttp4.get(accountId, {
      url: `/content/api/v4/contents/${contentId}`,
      params: { portalId },
      responseType: "json"
    })).data;
    return {
      previewDomain: content.previewDomain ?? content.resolvedDomain,
      previewKey: content.previewKey,
      templatePath: content.templatePath
    };
  } catch (error) {
    if (error.statusCode === 403 && error.error.message.match(
      /^This oauth-token \([\w]+\) does not have proper permissions!/
    )) {
      const errorMessagePrefix = `Your personal access key is missing required scopes to preview a CMS page.
You may need to re-generate a new personal access key with the required scopes and re-run \`hs-auth\`, or you may not have this functionality enabled in your account
`;
      console.error("Error: ", errorMessagePrefix);
      console.error(error.error.message);
      throw new Error(`${errorMessagePrefix}
${error.error.message}`);
    } else {
      console.log(`fetchPreviewInfo Error`, error);
      if (error.options) {
        console.log(`error.options`, error.options);
      }
      if (error.response && error.response.headers) {
        console.log(`error.response.headers`, error.response.headers);
      }
      throw error;
    }
  }
};

// src/proxyPage/proxyPage.ts
import {
  buildStaticEnvConfig,
  isDebugUrlString as isDebugUrlString3,
  mergeServerRequestData_internal
} from "@hubspot/cms-components";

// src/lib/previewUtils.ts
import { stringify } from "querystring";
import { readFileSync as readFileSync3 } from "fs";
import crypto from "crypto";
import { relative, join as join3 } from "path";

// src/api/session.ts
import { http as hsCliHttp5 } from "@hubspot/local-dev-lib/http";
var PREVIEW_API_PATH = `local-preview/v1`;
function initiateSession(accountId, resetSession = false) {
  return hsCliHttp5.post(accountId, {
    url: `${PREVIEW_API_PATH}/session/create`,
    headers: {
      "Content-Type": "application/json"
    },
    data: {
      resetSession
    }
  });
}
function diffDeveloperFileHashes(accountId, token, fileHashes) {
  return hsCliHttp5.post(accountId, {
    url: `${PREVIEW_API_PATH}/developer-file-hashes/diff`,
    headers: {
      "Content-Type": "application/json"
    },
    data: {
      token,
      fileHashes
    }
  });
}

// src/fileManager.ts
import { uploadFolder } from "@hubspot/local-dev-lib/cms/uploadFolder";
import chokidar from "chokidar";
import path3 from "path";
import { shouldIgnoreFile } from "@hubspot/local-dev-lib/ignoreRules";
import {
  convertToUnixPath,
  isAllowedExtension
} from "@hubspot/local-dev-lib/path";
import { normalizePath as normalizePath2 } from "vite";
import { getExt, splitLocalPath } from "@hubspot/local-dev-lib/path";
import { upload, deleteFile } from "@hubspot/local-dev-lib/api/fileMapper";
import { MODULE_EXTENSION } from "@hubspot/local-dev-lib/constants/extensions";
import { escapeRegExp } from "@hubspot/local-dev-lib/escapeRegExp";

// src/routes/remoteFsDirtyHandler.ts
var REMOTE_FS_IS_DIRTY = false;
var remoteFsDirtyHandler = (req, res) => {
  res.json({ REMOTE_FS_IS_DIRTY });
  REMOTE_FS_IS_DIRTY = false;
};
var markRemoteFsDirty = () => {
  REMOTE_FS_IS_DIRTY = true;
};

// src/fileManager.ts
async function initialPreviewBufferUpload(accountId, src, dest, filePaths, uploadOptions) {
  const { onFinishCallback, ...rest } = uploadOptions;
  const results = await uploadFolder(
    accountId,
    src,
    dest,
    {},
    rest,
    filePaths.map(
      (filePath) => filePath.replaceAll(path3.sep, path3.posix.sep)
    )
  );
  onFinishCallback(results);
}
var startPreviewWatcher = async (accountId, src, dest) => {
  let watcherIsReady = false;
  const watcher = chokidar.watch(src, {
    ignoreInitial: true,
    // makes initial addition of files not trigger the watcher
    ignored: (file) => shouldIgnoreFile(file)
  });
  const addFileCallback = buildUploadFileToPreviewBufferCallback(
    accountId,
    src,
    dest
  );
  const changeFileCallback = buildUploadFileToPreviewBufferCallback(
    accountId,
    src,
    dest
  );
  const deleteFileCallback = buildDeleteFileFromPreviewBufferCallback(
    accountId,
    src,
    dest,
    "file"
  );
  const deleteFolderCallback = buildDeleteFileFromPreviewBufferCallback(
    accountId,
    src,
    dest,
    "folder"
  );
  watcher.on("ready", () => {
    watcherIsReady = true;
  });
  watcher.on("add", addFileCallback);
  watcher.on("change", changeFileCallback);
  watcher.on(
    "error",
    (error) => console.error(`An error occurred while watching files: ${error}`)
  );
  watcher.on("unlink", deleteFileCallback);
  watcher.on("unlinkDir", deleteFolderCallback);
  function sleep(ms) {
    return new Promise((resolve2) => {
      setTimeout(resolve2, ms);
    });
  }
  while (!watcherIsReady) {
    await sleep(1);
  }
  return watcher;
};
function buildUploadFileToPreviewBufferCallback(accountId, src, dest) {
  return (filePath) => {
    if (!isAllowedExtension(filePath)) {
      console.debug(`Skipping ${filePath} due to unsupported extension`);
      return;
    }
    if (shouldIgnoreFile(filePath)) {
      console.debug(`Skipping ${filePath} due to an ignore rule`);
      return;
    }
    if (path3.dirname(filePath) === src && ["theme.json", "fields.json"].includes(path3.basename(filePath))) {
      console.warn(`Editing of theme fields or meta is not yet supported.`);
      return;
    }
    const destPath = getDesignManagerPath(src, dest, filePath);
    return uploadFile(accountId, filePath, destPath);
  };
}
function buildDeleteFileFromPreviewBufferCallback(accountId, src, dest, type) {
  return (filePath) => {
    if (shouldIgnoreFile(filePath)) {
      console.debug(`Skipping ${filePath} due to an ignore rule`);
      return;
    }
    if (type === "file") {
      const moduleChild = isModuleFolderChild(filePath);
      const filename = path3.basename(filePath);
      if (moduleChild && filename === "meta.json") {
        return;
      }
    }
    const remotePath = getDesignManagerPath(src, dest, filePath);
    return deleteRemoteFile(accountId, remotePath);
  };
}
function getDesignManagerPath(src, dest, file) {
  const normalizedSrc = normalizePath2(src);
  const normalizedFile = normalizePath2(file);
  const regex = new RegExp(`^${escapeRegExp(normalizedSrc)}`);
  const relativePath = normalizedFile.replace(regex, "");
  return convertToUnixPath(path3.join(dest, relativePath));
}
async function uploadFile(accountId, src, dest) {
  console.debug(`Attempting to upload file "${src}" to "${dest}"`);
  try {
    await upload(accountId, src, dest);
    console.log(`Uploaded file ${src} to ${dest}`);
    markRemoteFsDirty();
  } catch {
    const uploadFailureMessage = `Uploading file ${src} to ${dest} failed`;
    console.debug(uploadFailureMessage);
    console.debug(`Retrying to upload file "${src}" to "${dest}"`);
    try {
      await upload(accountId, src, dest);
      markRemoteFsDirty();
    } catch (error) {
      console.error(uploadFailureMessage);
    }
  }
}
async function deleteRemoteFile(accountId, remoteFilePath) {
  console.debug(`Attempting to delete file "${remoteFilePath}"`);
  try {
    await deleteFile(accountId, remoteFilePath);
    console.log(`Deleted file ${remoteFilePath}`);
    markRemoteFsDirty();
  } catch (error) {
    console.error(`Deleting file ${remoteFilePath} failed`);
    console.debug(`Retrying deletion of file ${remoteFilePath}`);
    try {
      await deleteFile(accountId, remoteFilePath);
      markRemoteFsDirty();
    } catch (err) {
      console.error(`Deleting file ${remoteFilePath} failed`);
    }
  }
}
function isModuleFolderChild(filePath) {
  const pathParts = splitLocalPath(filePath);
  if (pathParts.length <= 1)
    return false;
  return pathParts.slice(0, pathParts.length - 1).some((part) => getExt(path3.normalize(part)) === MODULE_EXTENSION);
}

// src/lib/previewUtils.ts
import path4 from "path";
var removePreviewPrefix = (t2) => t2.split("/").slice(2).join("/");
var getPreviewUrl = (request, queryParams) => {
  const { authedPortalId, authedEnv, authedHublet, sslEnabled } = request.app.locals;
  const protocol = sslEnabled ? "https" : "http";
  return `${protocol}://${authedPortalId}.hubspotpreview${authedEnv === "qa" ? "qa" : ""}-${authedHublet}.com/_hcms/preview/template/multi?${stringify(queryParams)}`;
};
var buildHTMLResponse = (content) => {
  return `
    <!DOCTYPE html>
    <head>
    </head>
    <body>
      ${content}
    </body>
  `;
};
var insertAtEndOfBody = (html, script) => {
  const insertAt = (baseStr, index, insertStr) => {
    return `${baseStr.slice(0, index)}${insertStr}${baseStr.slice(index)}`;
  };
  const endOfBodyIndex = html.lastIndexOf("</body>");
  return insertAt(html, endOfBodyIndex, script);
};
var addRefreshScript = (html) => {
  const refreshScript = `
  <script>
  (() => {
    const MAX_WAIT = 16000;
    const NORMAL_WAIT_MS = 1000;
    const BACKOFF_RATIO = 2;
    let nextWait = NORMAL_WAIT_MS;
    let timeWaited = 0;

    setInterval(() => {
      timeWaited += NORMAL_WAIT_MS;
      if (timeWaited !== nextWait) return;
      timeWaited = 0;
      const res = fetch(window.location.origin + '/remote-fs-dirty')
        .then(async (res) => {
          const hsServerState = await res.json();
          if (hsServerState["REMOTE_FS_IS_DIRTY"]) {
            location.reload();
          }
          nextWait = NORMAL_WAIT_MS;
        })
        .catch(err => {
          if (nextWait * BACKOFF_RATIO <= MAX_WAIT) {
            nextWait *= BACKOFF_RATIO;
          }
          console.log('Disconnected from local server... (retrying in ' + nextWait / 1000 + 's)');
        });
    }, NORMAL_WAIT_MS);
  })();
  </script>
  `;
  return insertAtEndOfBody(html, refreshScript);
};
function buildDevFileHashTable(src, dest, filePaths) {
  return filePaths.reduce((acc, filePath) => {
    const relativePath = relative(src, filePath);
    const destPath = join3(dest, relativePath).replaceAll(
      path4.sep,
      path4.posix.sep
    );
    acc[`/${destPath}`] = getMd5Hash(filePath);
    return acc;
  }, {});
}
function getMd5Hash(filePath) {
  const fileContent = readFileSync3(filePath);
  const hash = crypto.createHash("md5");
  hash.update(fileContent);
  return hash.digest("hex");
}
async function initiatePreviewSession(authedPortalId, absoluteWebRoot, themePreviewOptions) {
  let res;
  try {
    res = (await initiateSession(authedPortalId, themePreviewOptions.resetSession)).data;
  } catch (err) {
    console.error(`Failed to initiate session: ${err}`);
    return;
  }
  const { token, tokenStatus } = res;
  if (token) {
    const { dest, filePaths, startProgressBar } = themePreviewOptions;
    const absoluteDest = `@preview/${token}/${dest}`;
    const nonJSRFilePaths = filePaths.filter(
      (filePath) => !filePath.startsWith(path4.join(absoluteWebRoot, "components"))
    );
    if (tokenStatus === "NEW") {
      console.log("Uploading for a new session...");
      const uploadOptions = startProgressBar(nonJSRFilePaths.length);
      await initialPreviewBufferUpload(
        authedPortalId,
        absoluteWebRoot,
        absoluteDest,
        nonJSRFilePaths,
        uploadOptions
      );
    } else if (tokenStatus === "REFRESHED") {
      console.log("Comparing files for refreshed session...");
      const hashes = await buildDevFileHashTable(
        absoluteWebRoot,
        absoluteDest,
        nonJSRFilePaths
      );
      let diffRes;
      try {
        diffRes = (await diffDeveloperFileHashes(authedPortalId, token, hashes)).data;
      } catch (err) {
        console.error(
          `Failed to diff developer file hashes: ${JSON.stringify(err)}`
        );
        return;
      }
      const {
        changedFiles,
        addedFiles
        /*, deletedFiles */
      } = diffRes;
      const filesToUpload = [...changedFiles, ...addedFiles].map((filePath) => {
        const relPath = path4.relative(absoluteDest, filePath.substring(1));
        return path4.join(absoluteWebRoot, relPath);
      });
      if (filesToUpload.length) {
        const uploadOptions = startProgressBar(filesToUpload.length);
        await initialPreviewBufferUpload(
          authedPortalId,
          absoluteWebRoot,
          absoluteDest,
          filesToUpload,
          uploadOptions
        );
      }
    }
    await startPreviewWatcher(authedPortalId, absoluteWebRoot, absoluteDest);
  }
  return { localPreviewToken: token, tokenStatus };
}

// src/proxyPage/proxyPage.ts
var getEntryPointBasePathFromProxyRequest = (request) => {
  if (!request) {
    return "";
  }
  const { path: requestPath, pathParamDict } = request;
  if (!pathParamDict || !pathParamDict.dynamic_slug) {
    return requestPath;
  }
  return requestPath.replace(pathParamDict.dynamic_slug, "");
};
function resolvePlaceholderPath(placeholderPath, projectName, projectComponent) {
  if (!process.env.DEFAULT_MODULE_PATH_REWRITE) {
    return placeholderPath;
  }
  const mappedPlaceholderPath = `@projects/${projectName}/${projectComponent}/components/modules/${process.env.DEFAULT_MODULE_PATH_REWRITE.split(":")[1]}`;
  if (placeholderPath.startsWith(`@default-modules/${projectName}/`) && placeholderPath.endsWith(
    process.env.DEFAULT_MODULE_PATH_REWRITE.split(":")[0]
  )) {
    return mappedPlaceholderPath;
  }
  return placeholderPath;
}
var makeProxyPreviewRequest = (accountId, urlToProxy, previewKey, contentId, projectName, environmentConfig, __jsRenderingGates, cookieHeader, localPreviewToken) => {
  const url3 = new URL(urlToProxy);
  const renderPreviewLocally = url3.searchParams.has("renderPreviewLocally");
  let proxiedQueryParams = {};
  let baseURL = url3.origin;
  let pathname = url3.pathname;
  const PARAMS_TO_IGNORE = ["renderPreviewLocally"];
  const queryKeys = Array.from(url3.searchParams.keys()).filter(
    (queryKey) => !PARAMS_TO_IGNORE.includes(queryKey)
  );
  for (const queryKey of queryKeys) {
    const values = url3.searchParams.getAll(queryKey);
    if (values.length > 1) {
      proxiedQueryParams[queryKey] = values;
    } else {
      proxiedQueryParams[queryKey] = values[0];
    }
  }
  const localProxyProject = process.env.DEFAULT_MODULE_PATH_REWRITE ? `@default-modules/${projectName}` : `@projects/${projectName}`;
  proxiedQueryParams = {
    ...proxiedQueryParams,
    hs_preview: `${previewKey}-${contentId}`,
    hsLocalProxyProject: localProxyProject,
    localProxySchemaVersion: "2",
    hsLoginVerifyDisabled: `${true}`
  };
  if (renderPreviewLocally) {
    proxiedQueryParams.hsDebugOverridePublicHost = url3.host;
    baseURL = `http://local.hubspot${environmentConfig.getInternalHSEnv() === "qa" ? "qa" : ""}.com`;
    pathname = `/cos-rendering/v1/public${url3.pathname}`;
  }
  if (localPreviewToken) {
    proxiedQueryParams = {
      ...proxiedQueryParams,
      localPreviewToken,
      hsCacheBuster: Date.now().toString()
    };
    delete proxiedQueryParams["hs_preview"];
  }
  console.log(
    `Proxying request to ${baseURL}${pathname}?${new URLSearchParams({
      ...proxiedQueryParams,
      previewKey,
      contentId
    }).toString()}`
  );
  try {
    const result = hsCliHttp6.get(accountId, {
      baseURL,
      url: pathname,
      params: proxiedQueryParams,
      responseType: "text",
      headers: {
        COOKIE: cookieHeader
      }
    });
    return result;
  } catch (error) {
    if (error.status >= 400 && error.status < 500 && !!error.response.data) {
      return error.response.data;
    } else {
      throw error;
    }
  }
};
function isRecord2(value) {
  return typeof value === "object" && value !== null;
}
function isModulePlaceholder(value) {
  return isRecord2(value) && isRecord2(value.json) && isRecord2(value.json.props) && isRecord2(value.json.props.fieldValues) && isRecord2(value.json.props.hublParameters);
}
var renderComponentForPlaceholder = (indexForThisRender, localRenderPlaceholder, webRoot, viteServer, pageUrl, basePath, environmentConfig, hsProjectJsonProjectName, webRootProjectComponent) => {
  const placeholderPath = resolvePlaceholderPath(
    localRenderPlaceholder.path,
    hsProjectJsonProjectName,
    webRootProjectComponent
  );
  const localRenderPlaceholderProps = localRenderPlaceholder.json.props;
  const [
    __projectIdentifier,
    projectFolder,
    projectComponentFolder,
    componentFolder,
    componentTypeFolder,
    componentFileName
  ] = placeholderPath.split("/");
  const partialPath = `${componentFolder}/${componentTypeFolder}/`;
  if (projectFolder !== hsProjectJsonProjectName) {
    throw new Error(
      `Unable to render component located outside of the project folder "${hsProjectJsonProjectName}". Components should be nested within the project folder. Check that the specified path is correct: ${placeholderPath}.`
    );
  } else if (projectComponentFolder !== webRootProjectComponent) {
    throw new Error(
      `The specified component folder "${projectComponentFolder}" does not match the webroot project component folder "${webRootProjectComponent}/${projectComponentFolder}" specified to the cms-dev-server. Components must be located within the webroot project folder. Check that the specified path is correct: ${placeholderPath}.`
    );
  }
  const resolvedPath = normalizePath3(
    path5.resolve(webRoot, partialPath, componentFileName)
  );
  const entryPointPath = [
    "@projects",
    webRootProjectComponent,
    projectComponentFolder,
    partialPath,
    componentFileName
  ].join("/");
  if (placeholderPath.startsWith("/fake/path/to/")) {
    return fakeRenderJsComponent(indexForThisRender);
  } else if (partialPath === ENTRY_POINTS_PATH) {
    return renderComponentForPlaceholderPartial(
      viteServer,
      resolvedPath,
      localRenderPlaceholderProps,
      pageUrl,
      basePath,
      environmentConfig,
      entryPointPath,
      indexForThisRender
    );
  } else if (partialPath === MODULE_FOLDER_PATH) {
    if (!isModulePlaceholder(localRenderPlaceholder)) {
      console.error(
        `Skipping local module render of ${componentFileName} <!-- proxy local render .. --> is missing necessary module prop keys (fieldValues? hublParameters?) `
      );
    } else {
      const localModuleRenderPlaceholder = {
        ...localRenderPlaceholder
      };
      return renderComponentForPlaceholderModule(
        viteServer,
        resolvedPath,
        localModuleRenderPlaceholder,
        pageUrl,
        basePath,
        environmentConfig,
        entryPointPath,
        indexForThisRender
      );
    }
  } else {
    throw new Error(`Unimplemented render of ${placeholderPath}.`);
  }
};
function renderComponentForPlaceholderPartial(viteServer, resolvedPath, localRenderPlaceholderProps, pageUrl, basePath, environmentConfig, entryPointPath, indexForThisRender) {
  return renderPartial_default(
    viteServer,
    resolvedPath,
    localRenderPlaceholderProps,
    pageUrl,
    basePath,
    environmentConfig,
    {
      identifierPrefix: getEntryPointHashWithIndexSuffix(
        entryPointPath,
        indexForThisRender
      )
    }
  );
}
function renderComponentForPlaceholderModule(viteServer, resolvedPath, localModuleRenderPlaceholder, pageUrl, basePath, environmentConfig, entryPointPath, indexForThisRender) {
  return renderModule_default(
    viteServer,
    resolvedPath,
    localModuleRenderPlaceholder.json.props,
    pageUrl,
    basePath,
    environmentConfig,
    {
      identifierPrefix: getEntryPointHashWithIndexSuffix(
        entryPointPath,
        indexForThisRender
      )
    }
  );
}
async function proxySpecificPage(request, response, portalId, hublet, contentId, webRoot, viteServer, projectName, projectComponentPath, jsRenderingGates, urlToProxy, fullOriginalUrl) {
  let account;
  let proxyEnv;
  const prettyPrint = isDebugUrlString3(urlToProxy);
  try {
    account = getConfigAccountIfExists2(portalId);
    if (!account) {
      throw new Error();
    }
    proxyEnv = account == null ? void 0 : account.env;
  } catch (e) {
    response.status(500).end(
      `Unable to find account for hubid = ${portalId}. Please check your hubspot.config.yaml`
    );
    return;
  }
  if (!account) {
    response.status(500).end(
      `Unable to find account for hubid = ${portalId}. Please check your hubspot.config.yaml`
    );
    return;
  }
  try {
    const previewInfo = await fetchPreviewInfo_default(
      account.accountId,
      portalId,
      contentId
    );
    const { previewKey } = previewInfo;
    const environmentConfig = buildStaticEnvConfig(
      portalId,
      hublet,
      proxyEnv,
      false,
      jsRenderingGates
    );
    let pageHtml = (await makeProxyPreviewRequest(
      account.accountId,
      urlToProxy,
      previewKey,
      contentId,
      projectName,
      environmentConfig,
      jsRenderingGates,
      request.get("COOKIE"),
      request.app.locals.localPreviewToken
    )).data;
    pageHtml = addRefreshScript(pageHtml);
    await infillReactModulesAndWriteResponse(
      response,
      pageHtml,
      webRoot,
      fullOriginalUrl,
      environmentConfig,
      viteServer,
      projectName,
      projectComponentPath,
      jsRenderingGates,
      prettyPrint
    );
  } catch (error) {
    response.status(500).end(
      `Failed proxy render of page id = ${contentId} hub id = ${portalId}

${error.stack}`
    );
    return;
  }
}
async function infillReactModulesAndWriteResponse(response, pageHtml, webRoot, fullOriginalUrl, environmentConfig, viteServer, projectName, projectComponentPath, jsRenderingGates, prettyPrint) {
  const { sortIslandRootsByPriority } = await viteServer.ssrLoadModule(
    "@hubspot/cms-components"
  );
  const localRenderPlaceholders = findLocalRenderPlaceholders(pageHtml);
  const numPlaceholders = localRenderPlaceholders.length;
  let numJsRenderFailures = 0;
  let islands = [];
  let mergedPerRequestState = /* @__PURE__ */ new Map();
  let basePath;
  const criticalDevErrors = [];
  const renderPromisesByChunkIndex = new Array(
    numPlaceholders
  );
  if (localRenderPlaceholders.length > 0) {
    let offsetSoFar = 0;
    const pageChunks = new Array(numPlaceholders + 1);
    for (let indexForThisRender = 0; indexForThisRender < numPlaceholders; indexForThisRender++) {
      const localRenderPlaceholder = localRenderPlaceholders[indexForThisRender];
      pageChunks[indexForThisRender] = pageHtml.slice(
        offsetSoFar,
        localRenderPlaceholder.startOffset
      );
      if (basePath === void 0) {
        basePath = getEntryPointBasePathFromProxyRequest(
          localRenderPlaceholder.json.request
        );
      }
      const renderPromise = renderComponentForPlaceholder(
        indexForThisRender,
        localRenderPlaceholder,
        webRoot,
        viteServer,
        fullOriginalUrl,
        basePath,
        environmentConfig,
        projectName,
        projectComponentPath
      );
      renderPromisesByChunkIndex[indexForThisRender] = renderPromise.then((promiseResult) => {
        var _a;
        let { html, cssNeeded, inlineAssets, renderContext } = promiseResult;
        console.log(
          `Finished render of ${localRenderPlaceholder.path} (i = ${indexForThisRender})`
        );
        if ((_a = renderContext.criticalDevErrors) == null ? void 0 : _a.length) {
          criticalDevErrors.push(...renderContext.criticalDevErrors);
        }
        if (renderContext.islands.length > 0) {
          islands = islands.concat(renderContext.islands);
        }
        mergedPerRequestState = mergeServerRequestData_internal(
          mergedPerRequestState,
          renderContext.perServerRequestData
        );
        let result = html;
        if (inlineAssets) {
          result = `${inlineAssets.map((inlineAsset) => inlineAsset.html).join("\n")}
${result}`;
        }
        if (cssNeeded) {
          result = `${cssNeeded}
${result}`;
        }
        return result;
      }).catch((e) => {
        numJsRenderFailures += 1;
        console.log(
          "Attempted to render",
          localRenderPlaceholder.path,
          "with props",
          localRenderPlaceholder.json
        );
        console.error(e);
        return renderLocalError_default(localRenderPlaceholder.path, e);
      });
      offsetSoFar = localRenderPlaceholder.endOffset;
    }
    pageChunks[localRenderPlaceholders.length] = pageHtml.slice(offsetSoFar);
    response.writeHead(200);
    for (let i = 0; i < localRenderPlaceholders.length; i++) {
      const chunk = pageChunks[i];
      response.write(chunk);
      const foobar = await renderPromisesByChunkIndex[i];
      response.write(foobar);
    }
    response.write(
      getServerGlobalsToInject(
        environmentConfig,
        fullOriginalUrl,
        basePath,
        void 0,
        criticalDevErrors
      )
    );
    if (criticalDevErrors.length) {
      response.write(
        scriptTagToLogServerMessages(
          criticalDevErrorsToServerMessages_default(criticalDevErrors),
          "@hubspot/cms-dev-server messages"
        )
      );
    }
    if (islands.length > 0) {
      const sortedIslandRoots = sortIslandRootsByPriority(islands);
      const islandRuntimeAndGlobalScriptHtml = await getIslandRuntimeAndGlobalToInject(
        sortedIslandRoots,
        mergedPerRequestState,
        viteServer,
        jsRenderingGates,
        prettyPrint
      );
      response.write(islandRuntimeAndGlobalScriptHtml);
    }
    response.write(pageChunks[pageChunks.length - 1]);
    response.end();
  } else {
    response.writeHead(200);
    response.write(pageHtml);
    response.end();
  }
}

// src/lib/renderModulePreview.ts
import { http as hsCliHttp7 } from "@hubspot/local-dev-lib/http";
import { getConfigAccountIfExists as getConfigAccountIfExists3 } from "@hubspot/local-dev-lib/config";
import { accessTokenForPersonalAccessKey } from "@hubspot/local-dev-lib/personalAccessKey";
import jsdom from "jsdom";
var { JSDOM } = jsdom;
async function renderRemoteModulePreview(modulePath, authedPortalId, authedEnv, cookieValue) {
  const moduleInfoQueryParams = new URLSearchParams({
    portalId: `${authedPortalId}`
  });
  const moduleInfo = (await hsCliHttp7.get(authedPortalId, {
    url: `/api/designmanager/v1/modules/by-path/${encodeURIComponent(
      modulePath
    )}?${moduleInfoQueryParams}`,
    headers: {
      ["Accept"]: "application/json",
      referer: `https://app.hubspot${authedEnv === "qa" ? "qa" : ""}.com`,
      cookie: cookieValue,
      "User-Agent": "HubSpot CMS Dev Server"
    }
  })).data;
  const currentHubApiDomainOverride = process.env.HUBAPI_DOMAIN_OVERRIDE;
  process.env.HUBAPI_DOMAIN_OVERRIDE = `api.hubspot`;
  const queryParams = new URLSearchParams({
    portalId: `${authedPortalId}`,
    hsLocalProxy: `${true}`,
    localProxySchemaVersion: "2",
    hsLoginVerifyDisabled: `${true}`,
    module_id: moduleInfo.moduleId
  });
  const modulePreviewHtml = (await hsCliHttp7.get(authedPortalId, {
    url: `/api/cos-rendering/v1/public/_hcms/preview/template/multi?${queryParams}`,
    headers: {
      ["content-type"]: "application/x-www-form-urlencoded",
      ["Accept"]: "text/html",
      referer: `https://app.hubspot${authedEnv === "qa" ? "qa" : ""}.com`,
      cookie: cookieValue,
      "User-Agent": "HubSpot CMS Dev Server"
    }
  })).data;
  if (currentHubApiDomainOverride) {
    process.env.HUBAPI_DOMAIN_OVERRIDE = currentHubApiDomainOverride;
  } else {
    delete process.env.HUBAPI_DOMAIN_OVERRIDE;
  }
  const dom = new JSDOM(modulePreviewHtml);
  const modulePreviewContent = dom.window.document.querySelector(
    'div[data-hs-cos-type="module"]'
  ).outerHTML;
  const cssNeeded = Array.from(dom.window.document.querySelectorAll("style")).map((element) => element.outerHTML).join("");
  return { html: modulePreviewContent, cssNeeded };
}
async function signUrl(authedPortalId, unsignedUrl, requestBody) {
  const formData = {
    module: [JSON.stringify(requestBody)]
  };
  const request = {
    unsignedUrl,
    httpMethod: "POST",
    formData
  };
  try {
    const response = await hsCliHttp7.post(authedPortalId, {
      url: "/url-signer-rest/v1/signing/for-form",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      data: JSON.stringify(request)
    });
    return response.data.signedUrl;
  } catch (error) {
    console.error("Error signing URL:", error);
    throw error;
  }
}
async function renderLocalProjectModulePreview(moduleName, authedPortalId, authedEnv, authedHublet, webRoot, viteServer, jsRenderingGates, projectName, projectComponentPath, fullOriginalUrl, cookieValue, fieldOverrides = {}) {
  const modulePath = normalizePath4(
    path6.resolve(webRoot, "components/modules/", moduleName)
  );
  const basePath = `preview/${getEntryPointBasePath(modulePath)}`;
  const environmentConfig = buildStaticEnvConfig2(
    authedPortalId,
    authedHublet,
    authedEnv,
    false,
    jsRenderingGates
  );
  let componentModule;
  let foundPath;
  if (!hasComponentExtension(modulePath)) {
    [componentModule, foundPath] = await lookForModuleInFolder2(
      modulePath,
      viteServer
    );
  }
  if (!componentModule) {
    componentModule = await viteServer.ssrLoadModule(modulePath);
    foundPath = componentModule ? modulePath : void 0;
  }
  if (!componentModule) {
    throw new Error(`Couldn't find module: ${modulePath}`);
  }
  const Component = componentModule.Component;
  const fields = componentModule.fields;
  const meta = componentModule.meta;
  const hublDataTemplate = componentModule.hublDataTemplate;
  if (!Component) {
    throw new Error(
      `Module does not have a named Component export: ${foundPath}`
    );
  } else if (!fields) {
    throw new Error(`Module does not have a named fields export: ${foundPath}`);
  } else if (!meta) {
    throw new Error(`Module does not have a named meta export: ${foundPath}`);
  }
  const internalSsrPath = packagePath(import.meta.url, "internalSsr");
  const { renderFieldsToJson } = await viteServer.ssrLoadModule(internalSsrPath);
  const localFieldsJson = renderFieldsToJson(fields, modulePath);
  const localFieldValues = getFieldValuesForModule(
    localFieldsJson,
    fieldOverrides
  );
  const localModule = {
    isJsModule: true,
    schemaVersion: 2,
    fields: localFieldsJson,
    id: 1,
    path: `@projects/${projectName}/${projectComponentPath}/components/modules/${moduleName}`,
    hublDataTemplate
  };
  const queryParams = new URLSearchParams({
    hsLocalProxy: `${true}`,
    localProxySchemaVersion: "2",
    portalId: `${authedPortalId}`
  });
  const currentHubApiDomainOverride = process.env.HUBAPI_DOMAIN_OVERRIDE;
  process.env.HUBAPI_DOMAIN_OVERRIDE = `api.hubspot`;
  const previewDomain = `https://${authedPortalId}.hubspotpreview${authedEnv === "qa" ? "qa" : ""}-${authedHublet}.com`;
  const templatePreviewPath = `_hcms/preview/template/multiform`;
  const unsignedUrl = `${previewDomain}/${templatePreviewPath}?${queryParams}`;
  const signedUrl = await signUrl(authedPortalId, unsignedUrl, localModule);
  const postBody = `module=${encodeURIComponent(JSON.stringify(localModule))}`;
  let templatePreview;
  try {
    const authHeaders = {};
    const accountConfig = getConfigAccountIfExists3(authedPortalId);
    if (accountConfig && accountConfig.authType === "personalaccesskey") {
      const accessToken = await accessTokenForPersonalAccessKey(authedPortalId);
      authHeaders["Authorization"] = `Bearer ${accessToken}`;
    }
    const response = await fetch(signedUrl, {
      method: "POST",
      headers: {
        "content-type": "application/x-www-form-urlencoded",
        Accept: "text/html",
        referer: `https://api.hubspot${authedEnv === "qa" ? "qa" : ""}.com`,
        cookie: cookieValue,
        "User-Agent": "HubSpot CMS Dev Server",
        ...authHeaders
      },
      body: postBody
    });
    templatePreview = await response.text();
  } catch (error) {
    console.error("Preview request failed:", error);
    throw error;
  }
  if (currentHubApiDomainOverride) {
    process.env.HUBAPI_DOMAIN_OVERRIDE = currentHubApiDomainOverride;
  } else {
    delete process.env.HUBAPI_DOMAIN_OVERRIDE;
  }
  const localRenderPlaceholders = findLocalRenderPlaceholders(templatePreview);
  if (localRenderPlaceholders.length !== 1) {
    throw new Error(
      `Error previewing module (${moduleName}), exception in module preview HTML

`
    );
  }
  localRenderPlaceholders[0].json.props.fieldValues = localFieldValues;
  return await renderComponentForPlaceholder(
    0,
    localRenderPlaceholders[0],
    webRoot,
    viteServer,
    fullOriginalUrl,
    basePath,
    environmentConfig,
    projectName,
    projectComponentPath
  );
}

// src/routes/partial.ts
import { join as joinPosix3 } from "path/posix";
var partialRouteHandler = async (request, response) => {
  sendTrackingRequest("view-partial-route");
  const {
    authedPortalId,
    authedEnv,
    authedHublet,
    webRoot,
    viteServer,
    jsRenderingGates,
    projectName,
    projectComponentPath
  } = request.app.locals;
  const partialName = request.params.partial;
  const baseTemplatePath = packagePath(
    import.meta.url,
    "html/baseTemplate.html"
  );
  const partialPath = normalizePath5(
    path7.resolve(webRoot, "components/partials/", partialName)
  );
  const entrypointPath = normalizePath5(
    [
      "@projects",
      projectName,
      projectComponentPath,
      "components/modules/",
      partialName
    ].join("/")
  );
  const basePath = getEntryPointBasePath(partialPath);
  const environmentConfig = buildStaticEnvConfig3(
    authedPortalId,
    authedHublet,
    authedEnv,
    false,
    jsRenderingGates
  );
  try {
    const {
      html: renderedHtml,
      cssNeeded,
      renderContext,
      inlineAssets
    } = await renderPartial_default(
      viteServer,
      partialPath,
      {},
      fullOriginalUrlFromRequest(request),
      basePath,
      environmentConfig,
      {
        identifierPrefix: getEntryPointHash(entrypointPath)
      }
    );
    let resolvedCss = cssNeeded;
    let resolvedInlineAssets = inlineAssets;
    let partialHtml = renderedHtml;
    if (jsRenderingGates.includes("CMS:JSRenderer:AnalyzeCmsModules")) {
      const moduleNode = await viteServer.moduleGraph.getModuleByUrl(
        hasComponentExtension(partialPath) ? partialPath : joinPosix3(partialPath, "index")
      );
      if (!moduleNode) {
        throw new Error(`Error: could not find partial: ${partialPath}`);
      }
      const moduleInfo = viteServer.pluginContainer.getModuleInfo(
        moduleNode.id
      );
      const cmsModules = moduleInfo.meta.findCmsModules ?? {};
      const localProjectModules = Object.values(cmsModules).filter(
        (moduleDescriptor) => moduleDescriptor.path.startsWith(
          `@projects/${projectName}/${projectComponentPath}/components/modules/`
        )
      );
      const remoteModules = Object.values(cmsModules).filter(
        (moduleDescriptor) => !moduleDescriptor.path.startsWith(
          `@projects/${projectName}/${projectComponentPath}/components/modules/`
        )
      );
      const remoteModulePreviewPromises = [];
      const localProjectModulePreviewPromises = [];
      for (const remoteModule of remoteModules) {
        const modulePlaceholder = createModulePlaceholder(remoteModule.name);
        if (!renderedHtml.includes(modulePlaceholder))
          continue;
        remoteModulePreviewPromises.push(
          renderRemoteModulePreview(
            remoteModule.path,
            authedPortalId,
            authedEnv,
            request.get("COOKIE")
          ).then((result) => ({
            remoteModule,
            result
          }))
        );
      }
      for (const localProjectModule of localProjectModules) {
        const modulePlaceholder = createModulePlaceholder(
          localProjectModule.name
        );
        if (!renderedHtml.includes(modulePlaceholder))
          continue;
        localProjectModulePreviewPromises.push(
          renderLocalProjectModulePreview(
            path7.basename(localProjectModule.path),
            authedPortalId,
            authedEnv,
            authedHublet,
            webRoot,
            viteServer,
            jsRenderingGates,
            projectName,
            projectComponentPath,
            fullOriginalUrlFromRequest(request),
            request.get("COOKIE")
          ).then((result) => ({
            localProjectModule,
            result
          }))
        );
      }
      const [remoteModuleResults, localProjectModuleResults] = await Promise.all([
        Promise.all(remoteModulePreviewPromises),
        Promise.all(localProjectModulePreviewPromises)
      ]);
      for (const { remoteModule, result } of remoteModuleResults) {
        const modulePlaceholder = createModulePlaceholder(remoteModule.name);
        partialHtml = partialHtml.replace(modulePlaceholder, result.html);
        resolvedCss = resolvedCss.concat(result.cssNeeded);
      }
      for (const { localProjectModule, result } of localProjectModuleResults) {
        const modulePlaceholder = createModulePlaceholder(
          localProjectModule.name
        );
        renderContext.islands.push(...result.renderContext.islands);
        resolvedCss = resolvedCss.concat(result.cssNeeded);
        resolvedInlineAssets = resolvedInlineAssets.concat(result.inlineAssets);
        partialHtml = partialHtml.replace(modulePlaceholder, result.html);
      }
    }
    const htmlShell = await createHtmlShellDependingOnRenderContext(
      baseTemplatePath,
      request.originalUrl,
      `Partial: ${partialPath}`,
      renderContext,
      viteServer,
      jsRenderingGates
    );
    const html = htmlShell.replace(
      "<!--headend-->",
      [
        resolvedCss,
        ...resolvedInlineAssets.map((inlineAsset) => inlineAsset.html)
      ].join("\n")
    ).replace(`<!--ssr-outlet-->`, partialHtml);
    response.status(200).set({ "Content-Type": "text/html" }).end(html);
  } catch (e) {
    console.error(e);
    viteServer.ssrFixStacktrace(e);
    response.status(500).end(`Error rendering partial (${partialName})

${e.stack}`);
  }
};
function createModulePlaceholder(moduleName) {
  return `<!-- hs-module-placeholder-${moduleName} -->`;
}
var partial_default = partialRouteHandler;

// src/components/PartialsList.tsx
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
function EmptyPartialsList({ webRoot }) {
  return /* @__PURE__ */ jsxs("p", { children: [
    "No partials in ",
    /* @__PURE__ */ jsxs("code", { children: [
      webRoot,
      "components/partials"
    ] })
  ] });
}
function PartialLinkInLI({ partialName }) {
  return /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2("a", { href: `/partial/${partialName}`, children: partialName }) });
}
function PartialsList({ webRoot, partialNames }) {
  if (partialNames.length === 0) {
    return /* @__PURE__ */ jsx2(EmptyPartialsList, { webRoot });
  }
  return /* @__PURE__ */ jsx2("ul", { children: partialNames.map((partialName) => /* @__PURE__ */ jsx2(PartialLinkInLI, { partialName }, partialName)) });
}

// src/routes/linksToAllPartialsRouteHandler.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
var linksToAllPartialRouteHandler = async (request, response) => {
  const { webRoot } = request.app.locals;
  const { partialNames } = findAllPartialsInRoot(webRoot);
  const { html: responseHtml } = await renderOnServer(
    /* @__PURE__ */ jsx3(PartialsList, { webRoot, partialNames })
  );
  response.status(200).set({ "Content-Type": "text/html" }).end(responseHtml);
};
var linksToAllPartialsRouteHandler_default = linksToAllPartialRouteHandler;

// src/components/ModulesList.tsx
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
function EmptyModulesList({ webRoot }) {
  return /* @__PURE__ */ jsxs2("p", { children: [
    "No modules in ",
    /* @__PURE__ */ jsxs2("code", { children: [
      webRoot,
      "components/modules"
    ] })
  ] });
}
function ModuleLinkInLI({ moduleName }) {
  return /* @__PURE__ */ jsxs2("li", { children: [
    /* @__PURE__ */ jsx4("a", { href: `/preview/module/${moduleName}`, children: moduleName }),
    " / ",
    /* @__PURE__ */ jsx4("a", { href: `/module/${moduleName}`, children: "Local Version" })
  ] });
}
function ModulesList({ webRoot, moduleNames }) {
  if (moduleNames.length === 0) {
    return /* @__PURE__ */ jsx4(EmptyModulesList, { webRoot });
  }
  return /* @__PURE__ */ jsx4("ul", { children: moduleNames.map((moduleName) => /* @__PURE__ */ jsx4(ModuleLinkInLI, { moduleName }, moduleName)) });
}
var ModulesList_default = ModulesList;

// src/routes/linksToAllModulesRouteHandler.tsx
import { jsx as jsx5 } from "react/jsx-runtime";
var linksToAllModuleRouteHandler = async (request, response) => {
  const { webRoot } = request.app.locals;
  const { moduleNames } = findAllModulesInRoot(webRoot);
  const { html: responseHtml } = await renderOnServer(
    /* @__PURE__ */ jsx5(ModulesList_default, { webRoot, moduleNames })
  );
  response.status(200).set({ "Content-Type": "text/html" }).end(responseHtml);
};
var linksToAllModulesRouteHandler_default = linksToAllModuleRouteHandler;

// src/routes/module.ts
import { buildStaticEnvConfig as buildStaticEnvConfig4 } from "@hubspot/cms-components";
import path8 from "path";
import { normalizePath as normalizePath6 } from "vite";
var moduleRouteHandler = async (request, response) => {
  sendTrackingRequest("view-module-route");
  const {
    authedPortalId,
    authedEnv,
    authedHublet,
    webRoot,
    viteServer,
    jsRenderingGates,
    projectName,
    projectComponentPath
  } = request.app.locals;
  const moduleName = request.params.moduleName;
  const baseTemplatePath = packagePath(
    import.meta.url,
    "html/baseTemplate.html"
  );
  const modulePath = normalizePath6(
    path8.resolve(webRoot, "components/modules/", moduleName)
  );
  const entrypointPath = normalizePath6(
    [
      "@projects",
      projectName,
      projectComponentPath,
      "components/modules/",
      moduleName
    ].join("/")
  );
  let fieldOverrides = null;
  if (request.query.fields) {
    try {
      if (typeof request.query.fields === "string") {
        fieldOverrides = JSON.parse(
          decodeURIComponent(request.query.fields.replace(/\+/g, "%20"))
        );
      }
    } catch (e) {
      console.error(
        `Error parsing field param for module ${moduleName}: ${request.query.fields}`
      );
    }
  }
  const basePath = getEntryPointBasePath(modulePath);
  const environmentConfig = buildStaticEnvConfig4(
    authedPortalId,
    authedHublet,
    authedEnv,
    false,
    jsRenderingGates
  );
  try {
    const {
      html: renderedHtml,
      cssNeeded,
      renderContext,
      inlineAssets
    } = await renderModule_default(
      viteServer,
      modulePath,
      {
        fieldValues: fieldOverrides,
        hublParameters: {},
        moduleName: `local-${moduleName}`
      },
      fullOriginalUrlFromRequest(request),
      basePath,
      environmentConfig,
      {
        identifierPrefix: getEntryPointHash(entrypointPath)
      }
    );
    const htmlShell = await createHtmlShellDependingOnRenderContext(
      baseTemplatePath,
      request.originalUrl,
      `Module: ${modulePath}`,
      renderContext,
      viteServer,
      jsRenderingGates
    );
    const html = htmlShell.replace(
      "<!--headend-->",
      [
        cssNeeded,
        ...inlineAssets.map((inlineAsset) => inlineAsset.html)
      ].join("\n")
    ).replace(`<!--ssr-outlet-->`, renderedHtml);
    response.status(200).set({ "Content-Type": "text/html" }).end(html);
  } catch (e) {
    console.error(e);
    viteServer.ssrFixStacktrace(e);
    response.status(500).end(`Error rendering module (${moduleName})

${e.stack}`);
  }
};
var module_default = moduleRouteHandler;

// src/routes/moduleFieldsJson.ts
import path9 from "path";
import { normalizePath as normalizePath7 } from "vite";

// src/lib/renderModuleFieldsJson.ts
import { join as joinPosix4 } from "path/posix";
var lookForModuleInFolder3 = async (modulePath, viteServer) => {
  let componentModule;
  const insideFolderPath = joinPosix4(modulePath, "index");
  try {
    componentModule = await viteServer.ssrLoadModule(insideFolderPath);
  } catch (e) {
    if (!e.message.includes("Failed to load url")) {
      throw e;
    }
  }
  return [componentModule, insideFolderPath];
};
async function renderModuleFieldsJson(viteServer, requestedModulePath) {
  let componentModule;
  try {
    if (!hasComponentExtension(requestedModulePath)) {
      [componentModule] = await lookForModuleInFolder3(
        requestedModulePath,
        viteServer
      );
    }
    if (!componentModule) {
      componentModule = await viteServer.ssrLoadModule(requestedModulePath);
    }
  } catch (error) {
    throw new Error(
      `Failed to load module ${requestedModulePath}: ${error.message}`
    );
  }
  if (!componentModule) {
    throw new Error(`Couldn't find module: ${requestedModulePath}`);
  }
  const internalSsrPath = packagePath(import.meta.url, "internalSsr");
  const { renderFieldsToJson } = await viteServer.ssrLoadModule(internalSsrPath);
  const fieldsJson = renderFieldsToJson(
    componentModule.fields,
    requestedModulePath
  );
  return fieldsJson;
}
var renderModuleFieldsJson_default = renderModuleFieldsJson;

// src/routes/moduleFieldsJson.ts
var moduleFieldsJsonRouteHandler = async (request, response) => {
  try {
    sendTrackingRequest("fields-json-route");
    const { webRoot, viteServer } = request.app.locals;
    const { moduleName } = request.params;
    const modulePath = normalizePath7(
      path9.resolve(webRoot, "components/modules/", moduleName)
    );
    const fieldsJson = await renderModuleFieldsJson_default(viteServer, modulePath);
    return response.status(200).set({ "Content-Type": "application/json" }).json(fieldsJson);
  } catch (error) {
    console.error("Error processing module fields.json:", error);
    return response.status(500).json({
      error: "Failed to process module fields"
    });
  }
};
var moduleFieldsJson_default = moduleFieldsJsonRouteHandler;

// src/proxyPage/fetchContentMetadata.ts
import http from "http";
import https from "https";
import { getConfigAccountIfExists as getConfigAccountIfExists4 } from "@hubspot/local-dev-lib/config";
async function requestPage(url3, redirects = 0, originalUrl) {
  if (redirects > 5) {
    throw new Error(
      `Hit too many redirects to HEAD requests for ${originalUrl}`
    );
  }
  return new Promise((resolve2, reject) => {
    const protocolAPI = url3.startsWith("https://") ? https : http;
    protocolAPI.request(
      url3,
      {
        method: "HEAD",
        headers: {
          // Keep this user agent, so we don't get 403s from the request
          ["User-Agent"]: "cms-dev-server"
        }
      },
      async (res) => {
        let portalIdHeader;
        let contentId;
        const isContentMembershipRedirect = Boolean(
          res.headers["x-hs-content-membership-redirect"]
        );
        if (isContentMembershipRedirect) {
          debug("Content Membership Redirect", res.headers);
          portalIdHeader = res.headers["x-hs-portal-id"];
          contentId = res.headers["x-hs-content-id"];
          if (portalIdHeader && contentId) {
            return resolve2({
              portalIdHeader,
              contentId,
              res
            });
          }
        }
        if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
          console.log(`Redirecting to ${res.headers.location} (from ${url3})`);
          return resolve2(
            requestPage(
              res.headers.location,
              redirects + 1,
              originalUrl ?? url3
            )
          );
        }
        portalIdHeader = res.headers["x-hs-hub-id"];
        contentId = res.headers["x-hs-content-id"];
        return resolve2({
          res,
          portalIdHeader,
          contentId
        });
      }
    ).on("error", (err) => {
      console.error(err);
      reject(err);
    }).end();
  });
}
async function fetchContentMetadata(url3, portalId) {
  const { portalIdHeader, contentId, res } = await requestPage(url3);
  if (Array.isArray(portalIdHeader) || Array.isArray(contentId)) {
    throw new Error(
      `There were multiple hub ID or content ID headers in the HEAD request to ${url3}`
    );
  } else {
    const portalIdFromResponse = parseInt(portalIdHeader, 10);
    const pageAccount = await getConfigAccountIfExists4(portalIdFromResponse);
    if (!pageAccount) {
      throw new Error(
        `No CLI auth for portal ${portalIdFromResponse} found, please run \`hs auth\``
      );
    }
    if (res.statusCode !== 200 && !(portalIdFromResponse && pageAccount && contentId)) {
      throw new Error(
        `${res.statusCode} ${res.statusMessage} - Unable to obtain HEAD information from ${url3}. ${res.statusCode === 429 && res.headers["retry-after"] ? `Retry after ${res.headers["retry-after"]} seconds.` : ""}`
      );
    } else if (!portalId || !contentId) {
      throw new Error(
        `Missing hub ID or content ID headers on HEAD request to ${url3}`
      );
    } else if (isNaN(portalId)) {
      throw new Error(
        `Hub ID from the HEAD request is not a number: '${portalId}' (${url3})`
      );
    }
    const hublet = "na1";
    return { portalId, contentId, hublet };
  }
}

// src/routes/proxyPageRouteHandler.ts
async function proxyPageRouteHandler(request, response, next) {
  sendTrackingRequest("view-proxy-page-route");
  const {
    viteServer,
    webRoot,
    projectName,
    projectComponentPath,
    jsRenderingGates
  } = request.app.locals;
  if (!request.accepts().includes("text/html")) {
    return response.sendStatus(404);
  }
  const fullOriginalUrl = fullOriginalUrlFromRequest(request);
  const domainToProxy = getSubDomainFromValidLocalDomain(request.hostname);
  const urlToProxy = `http://${domainToProxy}${request.originalUrl}`;
  if (!domainToProxy) {
    if (VALID_PROXY_DOMAIN_SUFFIXES.includes(request.hostname)) {
      const message = `Can't make a proxy request, you need to prepend the real page's domain to '${request.hostname}' (i.e. your.page.com.${request.hostname})`;
      consoleWarn(message);
      return response.status(400).send(message);
    } else {
      const message = `Can't make a proxy request, the domain '${request.hostname}' is not a valid proxy-able domain`;
      consoleWarn(message);
      return response.status(400).send(message);
    }
  }
  try {
    const { portalId, contentId, hublet } = await fetchContentMetadata(
      urlToProxy,
      request.app.locals.authedPortalId
    );
    await proxySpecificPage(
      request,
      response,
      portalId,
      hublet,
      contentId,
      webRoot,
      viteServer,
      projectName,
      projectComponentPath,
      jsRenderingGates,
      urlToProxy,
      fullOriginalUrl
    );
  } catch (e) {
    next(e);
  }
}

// src/routes/proxyPageResourceRedirect.ts
import fetch2 from "node-fetch";
var HCMS_PATH = "/_hcms/";
var HS_FS_PATH = "/hs-fs/";
var HUB_FS_PATH = "/hubfs/";
var isInternalCMSRoute = (req) => req.path.startsWith(HCMS_PATH) || req.path.startsWith(HS_FS_PATH) || req.path.startsWith(HUB_FS_PATH);
function proxyPageResourceRedirect(req, res, next) {
  const isAHtmlRequest = req.accepts().includes("text/html");
  if (isAHtmlRequest && !isInternalCMSRoute(req) || VALID_PROXY_DOMAIN_SUFFIXES.includes(req.hostname)) {
    next();
    return;
  }
  const domainToProxy = getSubDomainFromValidLocalDomain(req.hostname);
  const pathToProxy = req.originalUrl;
  const urlToProxy = `https://${domainToProxy}${pathToProxy}`;
  if (req.method === "GET") {
    fetch2(urlToProxy).then((response) => response.body.pipe(res)).catch((err) => console.log(err));
  } else {
    const contentType = req.headers["content-type"];
    const isSendingJSON = contentType && /\bjson\b/.test(req.headers["content-type"].toString());
    const headerEntries = Object.entries(req.headers).filter(([header]) => {
      if (
        // Need to reset these headers for https (and recompression/encoding?) to work properly
        ["host", "origin", "connection", "content-length"].includes(
          header.toLowerCase()
        ) || header.startsWith("sec-")
      ) {
        return false;
      }
      return true;
    });
    const headersToPass = Object.fromEntries(headerEntries);
    let body = void 0;
    if (req.body) {
      if (isSendingJSON) {
        body = JSON.stringify(req.body);
      } else {
        body = req.body.toString();
      }
    }
    fetch2(urlToProxy, {
      method: req.method,
      headers: headersToPass,
      body
    }).then((response) => response.body.pipe(res)).catch((err) => console.log(err));
  }
}

// src/components/HubLModulesList.tsx
import { jsx as jsx6 } from "react/jsx-runtime";
function HubLModulesList({ modules }) {
  return modules.length === 0 ? /* @__PURE__ */ jsx6("p", { children: "No modules found." }) : /* @__PURE__ */ jsx6("ul", { children: modules.map((module) => /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6("a", { href: `/hublmodule/${removePreviewPrefix(module.path)}`, children: removePreviewPrefix(module.path) }) }, module.moduleId)) });
}

// src/api/designmanager.ts
import { http as hsCliHttp8 } from "@hubspot/local-dev-lib/http";
var DESIGN_MANAGER_API_PATH = "designmanager/v1";
async function fetchHubLModules(accountId, previewToken, limit = 250) {
  return (await hsCliHttp8.get(accountId, {
    url: `${DESIGN_MANAGER_API_PATH}/modules/local-preview?previewToken=${previewToken}&limit=${limit}`
  })).data;
}
async function fetchPreviewTemplates(accountId, previewToken, limit = 250) {
  return (await hsCliHttp8.get(accountId, {
    url: `${DESIGN_MANAGER_API_PATH}/templates/local-preview?previewToken=${previewToken}&limit=${limit}`
  })).data;
}
async function fetchModuleByPath(accountId, path17) {
  return (await hsCliHttp8.get(accountId, {
    url: `${DESIGN_MANAGER_API_PATH}/modules/by-path/${path17}?portalId=${accountId}`
  })).data;
}
async function fetchTemplateByPath(accountId, path17) {
  return (await hsCliHttp8.get(accountId, {
    url: `${DESIGN_MANAGER_API_PATH}/templates/by-path/${path17}?portalId=${accountId}`
  })).data;
}
async function fetchModulePageDependencies(accountId, path17) {
  const url3 = `${DESIGN_MANAGER_API_PATH}/modules/list-pages?modulePath=${path17}`;
  return (await hsCliHttp8.get(accountId, { url: url3 })).data;
}

// src/components/HubLTemplatesList.tsx
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
function HubLTemplatesList({ templates }) {
  return templates.length === 0 ? /* @__PURE__ */ jsxs3("p", { children: [
    "No templates found ",
    JSON.stringify(templates)
  ] }) : /* @__PURE__ */ jsx7("ul", { children: templates.filter((t2) => isCodedFile(t2.filename)).map((template) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7("a", { href: `/template/${removePreviewPrefix(template.path)}`, children: removePreviewPrefix(template.path) }) }, template.previewKey)) });
}
var TEMPLATE_EXTENSION_REGEX = new RegExp(/(?<!module)\.html$/);
function isCodedFile(filePath) {
  return TEMPLATE_EXTENSION_REGEX.test(filePath);
}

// src/routes/legacyRouteHandler.tsx
import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
var legacyRouteHandler = async (request, response, next) => {
  const domainToProxy = getSubDomainFromValidLocalDomain(request.hostname);
  if (domainToProxy) {
    next();
    return;
  }
  sendTrackingRequest("view-legacy-home-route");
  const {
    authedPortalId,
    webRoot,
    storybookEnabled,
    devServerPort,
    localPreviewToken
  } = request.app.locals;
  const { partialNames } = findAllPartialsInRoot(webRoot);
  const { moduleNames } = findAllModulesInRoot(webRoot);
  const hublModuleData = await fetchHubLModules(
    authedPortalId,
    localPreviewToken
  );
  const hublTemplateData = await fetchPreviewTemplates(
    authedPortalId,
    localPreviewToken
  );
  const { html: responseHtml } = await renderOnServer(
    /* @__PURE__ */ jsxs4(Fragment, { children: [
      storybookEnabled ? /* @__PURE__ */ jsx8("h2", { children: /* @__PURE__ */ jsx8("a", { href: `//storybook.${request.hostname}:${devServerPort}`, children: "Storybook" }) }) : null,
      /* @__PURE__ */ jsx8("h2", { children: "Partials" }),
      /* @__PURE__ */ jsx8(PartialsList, { webRoot, partialNames }),
      /* @__PURE__ */ jsx8("h2", { children: "React modules" }),
      /* @__PURE__ */ jsx8(ModulesList_default, { webRoot, moduleNames }),
      /* @__PURE__ */ jsx8("h2", { children: "HubL modules" }),
      /* @__PURE__ */ jsx8(HubLModulesList, { modules: hublModuleData.objects }),
      /* @__PURE__ */ jsx8("h2", { children: "HubL templates" }),
      /* @__PURE__ */ jsx8(HubLTemplatesList, { templates: hublTemplateData.objects })
    ] })
  );
  response.status(200).set({ "Content-Type": "text/html" }).end(responseHtml);
};
var legacyRouteHandler_default = legacyRouteHandler;

// src/routes/proxyPathPageRouteHandler.tsx
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
async function proxyPathPageRouteHandler(request, response, next) {
  sendTrackingRequest("view-proxy-path-route");
  const {
    viteServer,
    webRoot,
    projectName,
    projectComponentPath,
    jsRenderingGates
  } = request.app.locals;
  if (!request.accepts().includes("text/html")) {
    return response.sendStatus(404);
  }
  if (!request.query.page) {
    const { html: responseHtml } = await renderOnServer(
      /* @__PURE__ */ jsxs5("div", { children: [
        /* @__PURE__ */ jsx9("h2", { children: "Local Proxy" }),
        /* @__PURE__ */ jsxs5("form", { action: "/proxy", children: [
          /* @__PURE__ */ jsx9("label", { htmlFor: "page", style: { display: "block" }, children: "Page URL" }),
          /* @__PURE__ */ jsx9(
            "input",
            {
              style: { width: "300px" },
              name: "page",
              type: "text",
              placeholder: "https://somecmspage.com/path"
            }
          ),
          /* @__PURE__ */ jsx9("button", { style: { display: "block" }, children: "Proxy" })
        ] })
      ] })
    );
    response.status(200).set({ "Content-Type": "text/html" }).end(responseHtml);
    return;
  }
  let proxyPageUrl;
  try {
    proxyPageUrl = new URL(request.query.page);
  } catch (e) {
    const message = "Please provide a valid page query parameter, e.g., http://localhost:3000/proxy?page=https://yourdomain.com/path";
    consoleWarn(message);
    response.status(400).send(message);
    return;
  }
  if (proxyPageUrl.searchParams.has("hs_preview")) {
    const message = `Can't make a proxy request, you cannot proxy URLs that include internal query params like hs_preview`;
    consoleWarn(message);
    return response.status(400).send(message);
  }
  try {
    const { portalId, contentId, hublet } = await fetchContentMetadata(
      proxyPageUrl.href,
      request.app.locals.authedPortalId
    );
    await proxySpecificPage(
      request,
      response,
      portalId,
      hublet,
      contentId,
      webRoot,
      viteServer,
      projectName,
      projectComponentPath,
      jsRenderingGates,
      proxyPageUrl.href,
      proxyPageUrl.href
    );
  } catch (e) {
    next(e);
  }
}

// src/routes/proxyPathPageResourceRedirect.ts
import fetch3 from "node-fetch";
var HCMS_PATH2 = "/_hcms/";
var HS_FS_PATH2 = "/hs-fs/";
var HUB_FS_PATH2 = "/hubfs/";
var isInternalCMSRoute2 = (req) => req.path.startsWith(HCMS_PATH2) || req.path.startsWith(HS_FS_PATH2) || req.path.startsWith(HUB_FS_PATH2);
function proxyPathPageResourceRedirect(req, res, next) {
  const isAHtmlRequest = req.accepts().includes("text/html");
  let proxyPageUrl;
  let refererUrl;
  try {
    refererUrl = new URL(req.headers.referer);
    proxyPageUrl = new URL(
      new URL(req.headers.referer).searchParams.get("page")
    );
  } catch (e) {
    next();
    return;
  }
  if (!refererUrl.pathname.startsWith("/proxy")) {
    next();
    return;
  }
  if (isAHtmlRequest && !isInternalCMSRoute2(req)) {
    const encodedPageUrl = encodeURIComponent(
      `${proxyPageUrl.origin}${req.url}`
    );
    res.redirect(`/proxy?page=${encodedPageUrl}`);
    return;
  }
  const urlToProxy = `https://${proxyPageUrl.host}${req.url}`;
  fetch3(urlToProxy).then((response) => response.body.pipe(res)).catch((err) => console.log(err));
}

// src/routes/proxyServerlessHandler.ts
import fetch4 from "node-fetch";
var localDomains = ["localhost", "hslocal.net"];
function proxyServerlessRequest(req, res, next) {
  const { method, headers } = req;
  let refererUrl;
  let domainToProxy;
  let body;
  if (!req.headers.referer) {
    console.log("unable to proxy serverless request, no referer header found");
    next();
    return;
  }
  try {
    refererUrl = new URL(req.headers.referer);
    const referrerDomain = refererUrl.hostname;
    if (localDomains.includes(referrerDomain)) {
      domainToProxy = req.app.locals.domainsToProxy[0];
    } else {
      domainToProxy = referrerDomain.replace(/\.localhost|\.hslocal\.net/, "");
    }
  } catch (e) {
    console.log("Error parsing referer URL:", e);
    next();
  }
  if (!domainToProxy) {
    console.log("No domain to proxy for serverless request, skipping...");
    next();
    return;
  }
  const urlToProxy = `${refererUrl.protocol}//${domainToProxy}${req.url}`;
  const contentType = headers["content-type"];
  const cookie = headers.cookie;
  if (req.body) {
    body = JSON.stringify(req.body);
  }
  const headersToPass = {
    ...contentType ? { "Content-Type": contentType } : {},
    ...cookie ? { COOKIE: cookie } : {}
  };
  const proxyLogArgs = [
    `attempting to proxy a ${method} serverless request to domain:`,
    domainToProxy,
    "for resource:",
    req.url
  ];
  if (body) {
    proxyLogArgs.push("with body:", body);
  }
  console.log(...proxyLogArgs);
  switch (method) {
    case "POST":
    case "DELETE":
    case "PUT":
      fetch4(urlToProxy, {
        method,
        body,
        headers: headersToPass
      }).then((response) => response.body.pipe(res)).catch((err) => console.log(err));
      break;
    default:
      fetch4(urlToProxy, {
        headers: headersToPass
      }).then((response) => response.body.pipe(res)).catch((err) => console.log(err));
  }
}

// src/routes/modulePreviewRouteHandler.ts
import path10 from "path";
import { normalizePath as normalizePath8 } from "vite";
async function modulePreviewRouteHandler(request, response) {
  sendTrackingRequest("view-module-preview-route");
  const {
    authedPortalId,
    authedEnv,
    authedHublet,
    webRoot,
    viteServer,
    jsRenderingGates,
    projectName,
    projectComponentPath
  } = request.app.locals;
  const moduleName = request.params.moduleName;
  const modulePath = normalizePath8(
    path10.resolve(webRoot, "components/modules/", moduleName)
  );
  const PREVIEWER_APP_PARAM = "hsPreviewerApp";
  let fieldOverrides = {};
  if (request.method === "POST" && request.body) {
    if (request.query[PREVIEWER_APP_PARAM] === "module" && request.body.module_data) {
      fieldOverrides = request.body.module_data;
    } else {
      fieldOverrides = request.body;
    }
    try {
      if (typeof fieldOverrides === "string") {
        const parsedFieldOverrides = JSON.parse(fieldOverrides);
        if (parsedFieldOverrides && typeof parsedFieldOverrides === "object" && !Array.isArray(parsedFieldOverrides)) {
          fieldOverrides = parsedFieldOverrides;
        } else {
          throw new Error("Parsed field overrides must be an object");
        }
      }
    } catch (e) {
      console.error(
        `Error parsing field for module "${moduleName}": ${e.message}`,
        "\nReceived value:",
        fieldOverrides
      );
    }
  } else if (request.query.fields) {
    try {
      if (typeof request.query.fields === "string") {
        fieldOverrides = JSON.parse(
          decodeURIComponent(request.query.fields.replace(/\+/g, "%20"))
        );
      }
    } catch (e) {
      console.error(
        `Error parsing field param for module ${moduleName}: ${request.query.fields}`
      );
    }
  }
  try {
    const {
      html: renderedHtml,
      cssNeeded,
      renderContext,
      inlineAssets
    } = await renderLocalProjectModulePreview(
      moduleName,
      authedPortalId,
      authedEnv,
      authedHublet,
      webRoot,
      viteServer,
      jsRenderingGates,
      projectName,
      projectComponentPath,
      fullOriginalUrlFromRequest(request),
      request.get("COOKIE"),
      fieldOverrides
    );
    const baseTemplatePath = packagePath(
      import.meta.url,
      "html/baseTemplate.html"
    );
    const htmlShell = await createHtmlShellDependingOnRenderContext(
      baseTemplatePath,
      request.originalUrl,
      `Module: ${modulePath}`,
      renderContext,
      viteServer,
      jsRenderingGates
    );
    const html = htmlShell.replace(
      "<!--headend-->",
      [
        cssNeeded,
        ...inlineAssets.map((inlineAsset) => inlineAsset.html)
      ].join("\n")
    ).replace(`<!--ssr-outlet-->`, renderedHtml);
    response.status(200).set({ "Content-Type": "text/html" }).end(html);
  } catch (e) {
    console.error(e);
    viteServer.ssrFixStacktrace(e);
    return response.status(500).end(`Error rendering module (${moduleName})

${e.stack}`);
  }
}
var modulePreviewRouteHandler_default = modulePreviewRouteHandler;

// src/routes/hublModuleRouteHandler.ts
import { http as hsCliHttp9 } from "@hubspot/local-dev-lib/http";
var hublModuleRouteHandler = async (request, response) => {
  sendTrackingRequest("view-hubl-module-route");
  const { authedPortalId, localPreviewToken, projectName } = request.app.locals;
  const { modulePath } = request.params;
  if (!modulePath) {
    response.status(200).set({ "Content-Type": "text/html" }).end(buildModuleIndex());
    return;
  }
  const projectPrefix = projectName ? "@projects/" : "";
  const calculatedPath = `@preview/${localPreviewToken}/${projectPrefix}${modulePath}.module`;
  let customWidgetInfo;
  try {
    customWidgetInfo = await fetchModuleByPath(authedPortalId, calculatedPath);
  } catch (err) {
    console.error(`Failed to fetch module data for ${calculatedPath}: ${err}`);
    response.status(500).set({ "Content-Type": "text/html" }).end(buildErrorIndex(err));
    return;
  }
  if (!customWidgetInfo || !("moduleId" in customWidgetInfo)) {
    response.status(500).set({ "Content-Type": "text/html" }).end(buildErrorIndex(null));
    return;
  }
  const params = {
    module_id: customWidgetInfo.moduleId,
    hs_preview_key: customWidgetInfo.previewKey,
    updated: Date.now(),
    ...request.query
  };
  const previewUrl = new URL(getPreviewUrl(request, params));
  try {
    const result = (await hsCliHttp9.get(authedPortalId, {
      baseURL: previewUrl.origin,
      url: previewUrl.pathname,
      params
    })).data;
    const html = addRefreshScript(result);
    response.status(200).set({ "Content-Type": "text/html" }).end(html);
  } catch (err) {
    console.log(err);
    response.status(500).set({ "Content-Type": "text/html" }).end(buildErrorIndex(err));
  }
};
var buildErrorIndex = (err) => buildHTMLResponse(`
  <div>
    <h2>Module</h2>
    <p>ERROR</p>
  </div>
`);
var buildModuleIndex = () => buildHTMLResponse(`
  <div>
    <h2>Module</h2>
    <p>Please provide a module path in the request</p>
  </div>
`);

// src/routes/hublTemplateRouteHandler.ts
import { http as hsCliHttp10 } from "@hubspot/local-dev-lib/http";
import { buildStaticEnvConfig as buildStaticEnvConfig5 } from "@hubspot/cms-components";
import { getConfigAccountEnvironment } from "@hubspot/local-dev-lib/config";
var HUBSPOT_PREVIEW_BASE_TAG_REGEX = /<base\s+[^>]*href=["'][^"']*(?:hubspotpreview(?:qa)?)[^"']*["'][^>]*>/i;
var templateRouteHandler = async (request, response) => {
  sendTrackingRequest("view-template-route");
  const {
    authedPortalId,
    localPreviewToken,
    projectName,
    viteServer,
    webRoot,
    projectComponentPath,
    jsRenderingGates
  } = request.app.locals;
  const environmentConfig = buildStaticEnvConfig5(
    authedPortalId,
    "na1",
    getConfigAccountEnvironment(authedPortalId),
    false,
    jsRenderingGates
  );
  const { templatePath } = request.params;
  if (!templatePath) {
    response.status(200).set({ "Content-Type": "text/html" }).end(buildTemplateIndex());
    return;
  }
  const calculatedPath = `@preview/${localPreviewToken}/${templatePath}`;
  let templateInfo;
  try {
    templateInfo = await fetchTemplateByPath(authedPortalId, calculatedPath);
  } catch (err) {
    console.error(
      `Failed to fetch template data for ${calculatedPath}: ${err}`
    );
  }
  if (!templateInfo || !("previewKey" in templateInfo)) {
    response.status(500).set({ "Content-Type": "text/html" }).end(buildErrorIndex2());
    return;
  }
  const localProxyProject = process.env.DEFAULT_MODULE_PATH_REWRITE ? `@default-modules/${projectName}` : `@projects/${projectName}`;
  const params = {
    template_file_path: calculatedPath,
    hs_preview_key: templateInfo.previewKey,
    localPreviewToken,
    hsLocalProxyProject: localProxyProject,
    localProxySchemaVersion: "2",
    hsLoginVerifyDisabled: `${true}`,
    hsCacheBuster: Date.now().toString(),
    ...request.query
  };
  const previewUrl = new URL(getPreviewUrl(request, params));
  const fullOriginalUrl = `${request.protocol}://${request.get("host")}${request.originalUrl}`;
  try {
    const result = (await hsCliHttp10.get(authedPortalId, {
      baseURL: previewUrl.origin,
      url: previewUrl.pathname,
      params
    })).data;
    const pageHtml = addRefreshScript(result);
    const finalHtml = pageHtml.replace(
      HUBSPOT_PREVIEW_BASE_TAG_REGEX,
      '<base href="/" />'
    );
    infillReactModulesAndWriteResponse(
      response,
      finalHtml,
      webRoot,
      fullOriginalUrl,
      environmentConfig,
      viteServer,
      projectName,
      projectComponentPath,
      jsRenderingGates,
      false
    );
  } catch (err) {
    response.status(500).set({ "Content-Type": "text/html" }).end(buildErrorIndex2());
  }
};
function buildErrorIndex2() {
  return buildHTMLResponse(`
    <div>
      <h2>Error</h2>
      <p>Failed to fetch template data.</p>
    </div>
  `);
}
function buildTemplateIndex() {
  return buildHTMLResponse(`
    <div>
      <h2>Template</h2>
      <p>Please provide a template path in the request</p>
    </div>
  `);
}

// src/routes/createAppServerAPIRoutes.ts
import { Router } from "express";
import { spawn } from "child_process";
function getOpenCommand() {
  switch (process.platform) {
    case "darwin":
      return "open";
    case "win32":
      return "start";
    default:
      return "xdg-open";
  }
}
async function handleGetModulePages(req, res, next) {
  const { path: path17, portalId } = req.query;
  if (!path17 || !portalId) {
    return res.status(400).json({ error: "Missing required parameters" });
  }
  try {
    sendTrackingRequest("handle-module-dependencies");
    const data = await fetchModulePageDependencies(
      Number(portalId),
      path17
    );
    res.json(data);
  } catch (err) {
    next(err);
  }
}
function handleOpenFile(req, res, next) {
  const { path: path17 } = req.query;
  if (!path17) {
    return res.status(400).json({ error: "Missing required parameters" });
  }
  try {
    sendTrackingRequest("handle-open-file");
    const command = getOpenCommand();
    spawn(command, [path17], { detached: true }).unref();
    res.sendStatus(200);
  } catch (err) {
    next(err);
  }
}
function createAppServerAPIRoutes() {
  const router = Router();
  router.get("/module-pages", handleGetModulePages);
  router.get("/open-file", handleOpenFile);
  return router;
}
var createAppServerAPIRoutes_default = createAppServerAPIRoutes;

// src/routes/appServerRouteHandler.ts
import fs4 from "node:fs/promises";
import path12 from "path";
import { pathToFileURL } from "url";

// src/lib/getDevServerUIData.ts
import path11 from "path";
import { normalizePath as normalizePath9 } from "vite";

// src/api/project.ts
import { http as hsCliHttp11 } from "@hubspot/local-dev-lib/http";
var DEVELOPER_PROJECTS_API_PATH = "/developer/projects/v1";
async function fetchProjectByName(accountId, projectName) {
  return (await hsCliHttp11.get(accountId, {
    url: `${DEVELOPER_PROJECTS_API_PATH}/by-name/${projectName}`
  })).data;
}

// src/lib/getDevServerUIData.ts
import fs3 from "node:fs";
var templateTypeMap = {
  // Standard templates
  4: "Page",
  2: "Email",
  42: "Blog Listing",
  41: "Blog Post",
  6: "Blog (Deprecated)",
  // Global partials
  38: "Global Partial",
  18: "Global Group",
  // System templates
  11: "Error Page",
  19: "Password Prompt",
  29: "Membership Login",
  30: "Membership Register",
  31: "Membership Reset",
  32: "Membership Reset Request",
  12: "Subscription Preferences",
  14: "Backup Unsubscribe",
  27: "Search Results"
};
function mapReactModules(modules, themeWebRoot, appViteServer) {
  return Promise.all(
    modules.moduleNames.map(async (name, index) => {
      const modulePath = normalizePath9(
        path11.resolve(themeWebRoot, "components/modules/", name)
      );
      const fieldsJson = await renderModuleFieldsJson_default(
        appViteServer,
        modulePath
      );
      return {
        name,
        type: "react" /* REACT */,
        subPath: modules.moduleSubpaths[index],
        nameWithExtension: modules.moduleNamesWithExtension[index],
        extension: modules.moduleExtensions[index],
        fieldsJson
      };
    })
  );
}
function normalizeHubLModules(modules, projectName) {
  return modules.map((module) => {
    const subPath = projectName ? `${module.path.split("/@projects/")[1] || module.path}` : removePreviewPrefix(module.path);
    return {
      name: module.name,
      type: "hubl" /* HUBL */,
      subPath,
      nameWithExtension: module.filename,
      fieldsJson: module.fields
    };
  });
}
function normalizePartialsData(partialData) {
  return partialData.partialNames.map((name, index) => ({
    name,
    subPath: partialData.partialSubpaths[index]
  }));
}
function normalizeTemplatesData(templates, projectName) {
  return templates.filter((template) => template.templateType in templateTypeMap).map((template) => {
    const subPath = projectName ? `@projects/${template.path.split("/@projects/")[1] || template.path}` : removePreviewPrefix(template.path);
    return {
      name: template.displayName || template.label,
      subPath,
      templateTypeLabel: templateTypeMap[template.templateType]
    };
  });
}
function detectPackageManager(projectRoot) {
  if (fs3.existsSync(path11.join(projectRoot, "yarn.lock")))
    return "yarn";
  if (fs3.existsSync(path11.join(projectRoot, "pnpm-lock.yaml")))
    return "pnpm";
  return "npm";
}
async function getDevServerUIData(appLocals) {
  const {
    themeWebRoot,
    authedEnv,
    authedPortalId,
    projectName,
    localPreviewToken,
    webRootProjectComponentFolder,
    sslEnabled,
    fieldBuilderEnabled,
    appViteServer
  } = appLocals;
  const modulesData = findAllModulesInRoot(themeWebRoot);
  const partialsData = findAllPartialsInRoot(themeWebRoot);
  let packageJson = { scripts: {} };
  let packageManager = "";
  let cliCommands = [];
  let reactModules = [];
  if (projectName) {
    packageJson = getPackageJson(themeWebRoot);
    packageManager = detectPackageManager(themeWebRoot);
    const runCommand = packageManager === "yarn" ? "yarn" : `${packageManager} run`;
    cliCommands = projectName ? Object.entries((packageJson == null ? void 0 : packageJson.scripts) || {}).map(
      ([scriptName, description]) => ({
        scriptName,
        description,
        runCommand: `${runCommand} ${scriptName}`
      })
    ) : [];
    reactModules = projectName ? await mapReactModules(modulesData, themeWebRoot, appViteServer) : [];
  }
  let hubLModuleData = { objects: [] };
  let hubLTemplateData = { objects: [] };
  let projectData = null;
  let normalizedHubLModules = [];
  if (authedPortalId) {
    try {
      const dataFetchingPromises = [
        fetchHubLModules(authedPortalId, localPreviewToken),
        fetchPreviewTemplates(authedPortalId, localPreviewToken),
        projectName ? fetchProjectByName(authedPortalId, projectName) : Promise.resolve(null)
      ];
      [hubLModuleData, hubLTemplateData, projectData] = await Promise.all(dataFetchingPromises);
    } catch (e) {
      console.warn("Error fetching data:", e);
    }
    normalizedHubLModules = normalizeHubLModules(
      (hubLModuleData == null ? void 0 : hubLModuleData.objects) || [],
      projectName
    );
  }
  return {
    authedPortalId,
    authedEnv,
    projectName,
    modulesData: reactModules,
    partialsData: normalizePartialsData(partialsData),
    hubLModules: normalizedHubLModules || [],
    hubLTemplates: normalizeTemplatesData(
      (hubLTemplateData == null ? void 0 : hubLTemplateData.objects) || [],
      projectName
    ),
    themeWebRoot,
    webRootProjectComponentFolder,
    cliCommands,
    sslEnabled,
    projectData,
    fieldBuilderEnabled
  };
}

// src/routes/appServerRouteHandler.ts
var isProd = true;
var appServerRouteHandler = async (req, res, __next) => {
  try {
    sendTrackingRequest("view-index-route");
    const appLocals = req.app.locals.appLocals;
    const { appWebRoot, appViteServer } = appLocals;
    const initialProps = await getDevServerUIData(appLocals);
    const url3 = req.originalUrl.replace("/", "");
    const templatePath = path12.join(appWebRoot, "index.html");
    const serverEntryPath = isProd ? path12.join(appWebRoot, "server/serverEntry.js") : path12.join(appWebRoot, "serverEntry.tsx");
    let render;
    let template = await fs4.readFile(path12.join(templatePath), "utf-8");
    if (isProd) {
      const { render: ssrRender } = await import(pathToFileURL(serverEntryPath).href);
      render = ssrRender;
    } else {
      template = await appViteServer.transformIndexHtml(url3, template);
      render = (await appViteServer.ssrLoadModule(serverEntryPath)).render;
    }
    const rendered = await render(initialProps);
    const html = template.replace(`<!--app-head-->`, rendered.head ?? "").replace(`<!--app-html-->`, rendered.html ?? "").replace(
      `<!--app-script-->`,
      `<script>window.__hsInitialProps = ${JSON.stringify(
        initialProps
      )};</script>` ?? ""
    );
    res.status(200).set({ "Content-Type": "text/html" }).send(html);
  } catch (e) {
    const { appViteServer } = req.app.locals.appLocals;
    appViteServer == null ? void 0 : appViteServer.ssrFixStacktrace(e);
    console.log(e.stack);
    res.status(500).end(e.stack);
  }
};
var appServerRouteHandler_default = appServerRouteHandler;

// src/routes/createDevServerRoutes.ts
import path13 from "path";
var isProd2 = true;
var STORYBOOK_DOMAINS = VALID_PROXY_DOMAIN_SUFFIXES.map(
  (domain) => `storybook.${domain}`
);
var createDevServerRoutes = async (viteServer, appLocals, storybookPort) => {
  const devServerApp = Router2();
  const { appViteServer, appWebRoot } = appLocals || {};
  devServerApp.use((request, response, next) => {
    const { method, url: url3, hostname } = request;
    debug(`${method}:${hostname}${url3}`);
    next();
  });
  if (storybookPort) {
    devServerApp.use(
      createProxyMiddleware2(
        (__pathname, req) => STORYBOOK_DOMAINS.includes(req.hostname),
        {
          logLevel: "warn",
          target: `http://localhost:${storybookPort}`
        }
      )
    );
  }
  devServerApp.use(urlencoded());
  if (isProd2) {
    const distAssetsPath = path13.join(appWebRoot, "assets");
    devServerApp.use("/assets", expressStatic(distAssetsPath));
  } else {
    devServerApp.use("/local", appViteServer.middlewares);
  }
  devServerApp.use(viteServer.middlewares);
  devServerApp.use("/api", createAppServerAPIRoutes_default());
  devServerApp.get("/", appServerRouteHandler_default);
  devServerApp.get("/legacy", legacyRouteHandler_default);
  devServerApp.get("/proxy", proxyPathPageRouteHandler);
  devServerApp.get("/partials/", linksToAllPartialsRouteHandler_default);
  devServerApp.get("/partial/:partial", partial_default);
  devServerApp.get("/partial/:partial/*", partial_default);
  devServerApp.get("/remote-fs-dirty", remoteFsDirtyHandler);
  devServerApp.get("/preview/module/:moduleName", modulePreviewRouteHandler_default);
  devServerApp.get("/modules/", linksToAllModulesRouteHandler_default);
  devServerApp.get("/module/:moduleName", module_default);
  devServerApp.get(
    "/preview/module/:moduleName/fields.json",
    moduleFieldsJson_default
  );
  devServerApp.get("/module/:moduleName/*", module_default);
  devServerApp.post("/preview/module/:moduleName", modulePreviewRouteHandler_default);
  devServerApp.get("/hublmodule/:modulePath(*)", hublModuleRouteHandler);
  devServerApp.get("/template/:templatePath(*)", templateRouteHandler);
  devServerApp.all("/hs/serverless/*", proxyServerlessRequest);
  devServerApp.all("/_hcms/api/*", proxyServerlessRequest);
  devServerApp.get("/*", proxyPathPageResourceRedirect);
  devServerApp.get("/*", proxyPageResourceRedirect);
  devServerApp.post("/*", proxyPageResourceRedirect);
  devServerApp.delete("/*", proxyPageResourceRedirect);
  devServerApp.head("/*", proxyPageResourceRedirect);
  devServerApp.put("/*", proxyPageResourceRedirect);
  devServerApp.options("/*", proxyPageResourceRedirect);
  devServerApp.get("/*", proxyPageRouteHandler);
  return devServerApp;
};
var createDevServerRoutes_default = createDevServerRoutes;

// src/shadowDevServer/startShadowDevServer.ts
import net from "net";
import express from "express";

// src/shadowDevServer/createShadowDevServerRoutes.ts
import { Router as Router3 } from "express";
import { getConfigAccountIfExists as getConfigAccountIfExists5 } from "@hubspot/local-dev-lib/config";
import cors from "cors";
function getShadowDevServerCheckHandler(devServerPort, themePath) {
  return async function shadowDevServerCheckHandler(request, response) {
    const { query } = request;
    if (query) {
      const {
        hostName,
        pathName,
        contentId,
        portalId: portalIdString
      } = query;
      const portalId = parseInt(portalIdString, 10);
      let account;
      let isTemplateFromDevTheme = false;
      let localProxyUrl;
      try {
        account = getConfigAccountIfExists5(portalId);
        if (!account) {
          throw new Error();
        }
      } catch (e) {
        response.status(500).end(
          `Unable to find account for hubid = ${portalId}. Please check your hubspot.config.yaml`
        );
        return;
      }
      try {
        const { templatePath } = await fetchPreviewInfo_default(
          account.accountId,
          portalId,
          contentId
        );
        if (templatePath.startsWith(themePath)) {
          isTemplateFromDevTheme = true;
          localProxyUrl = `http://${hostName}.hslocal.net:${devServerPort}${pathName}`;
        }
        response.status(200).set({ "Content-Type": "application/json" }).json({
          isTemplateFromDevTheme,
          localProxyUrl
        });
      } catch (error) {
        response.status(500).end(
          `Failed proxy render of page id = ${contentId} hub id = ${portalId}

${error.stack}`
        );
        return;
      }
    } else {
      response.status(500).end(
        `Missing pageUrl param, cannot check for proxied page without a pageUrl`
      );
    }
  };
}
async function createShadowDevServerRoutes(devServerPort, themePath) {
  const shadowDevServerRoutes = Router3();
  shadowDevServerRoutes.get(
    "/check-if-local-dev-server",
    cors(),
    getShadowDevServerCheckHandler(devServerPort, themePath)
  );
  return shadowDevServerRoutes;
}

// src/shadowDevServer/startShadowDevServer.ts
var testNetServer = net.createServer();
async function startShadowDevServer(devServerPort, shadowPort, themePath) {
  const portIsTaken = await new Promise((res, rej) => {
    console.log(`Starting proxy link server on port ${shadowPort}`);
    testNetServer.once("error", (err) => {
      if (err["code"] === "EADDRINUSE") {
        console.error(
          `Port ${shadowPort} is in use. HubSpot is unable to automatically create proxy links in the Sprocket Menu`
        );
        res(true);
      } else {
        rej(err);
      }
    });
    testNetServer.once("listening", () => {
      testNetServer.close();
    });
    testNetServer.once("close", () => {
      res(false);
    });
    testNetServer.listen(shadowPort);
  });
  if (portIsTaken) {
    return;
  }
  const shadowDevServer = express();
  shadowDevServer.listen(shadowPort);
  shadowDevServer.use(
    "/",
    await createShadowDevServerRoutes(devServerPort, themePath)
  );
}

// src/createAppServer.ts
import {
  createServer as createViteServer2
} from "vite";
import { createRequire as createRequire2 } from "module";
import { default as react2 } from "@vitejs/plugin-react";
import { default as mkcert2 } from "vite-plugin-mkcert";
var isProd3 = true;
async function createAppServer(appWebRoot, port, sslEnabled) {
  const origin = process.env.VITE_ORIGIN ?? (sslEnabled ? `https://hslocal.net:${port}` : `http://hslocal.net:${port}`);
  const viteConfig = {
    server: {
      middlewareMode: true,
      host: "hslocal.net",
      origin,
      hmr: {
        protocol: sslEnabled ? "wss" : "ws",
        port: port + 1
      }
    },
    appType: "custom",
    root: appWebRoot,
    base: isProd3 ? void 0 : "/local",
    ssr: {
      noExternal: "@hubspot/cms-components"
    },
    resolve: {
      conditions: ["server"],
      dedupe: ["react", "react-dom", "@hubspot/cms-components", "styled-jsx"],
      alias: {
        "@": appWebRoot
      }
    },
    optimizeDeps: {
      include: ["react", "react-dom", "react-dom/client"]
    },
    plugins: [
      (() => {
        const require2 = createRequire2(import.meta.url);
        return react2({
          babel: {
            plugins: [
              require2.resolve("babel-plugin-styled-components"),
              require2.resolve("styled-jsx/babel"),
              require2.resolve("babel-plugin-macros")
            ]
          }
        });
      })(),
      clientIslandEntryPlugin(),
      resolveIslandPlugin(),
      sslEnabled ? mkcert2() : null
    ],
    css: {
      postcss: appWebRoot
    },
    envDir: appWebRoot,
    envPrefix: "HS_"
  };
  return createViteServer2(viteConfig);
}
var createAppServer_default = createAppServer;

// src/lib/httpsRedirectingServer.ts
import net2 from "net";
import http2 from "http";
import https2 from "https";
function requireHTTPS(message, response) {
  const newLocation = `https://${message.headers.host}${message.url}`;
  response.writeHead(302, {
    Location: newLocation
  }).end();
}
function createHttpsRedirectingServer(opts, handler) {
  const innerHTTPServer = http2.createServer(requireHTTPS);
  const innerHTTPSServer = https2.createServer(opts, handler);
  const server = net2.createServer((socket) => {
    socket.once("data", (buffer) => {
      socket.pause();
      const byte = buffer[0];
      let protocol;
      if (byte === 22) {
        protocol = "https";
      } else if (32 < byte && byte < 127) {
        protocol = "http";
      } else {
        throw new Error(
          "Unknown issue with incoming data, unknown if http or https"
        );
      }
      const proxy = protocol === "http" ? innerHTTPServer : innerHTTPSServer;
      if (proxy) {
        socket.unshift(buffer);
        proxy.emit("connection", socket);
      }
      process.nextTick(() => socket.resume());
    });
  });
  return { server, innerHTTPServer, innerHTTPSServer };
}

// src/lib/getJSRenderingGates.ts
import { fetchAccessToken } from "@hubspot/local-dev-lib/api/localDevAuth";

// src/lib/gates.ts
function getGatesFromEnv() {
  const gates = process.env.GATES ? process.env.GATES.split(",") : [];
  return gates;
}

// src/lib/getJSRenderingGates.ts
var mapEnabledFeaturesToGates = (enabledFeatures) => {
  return Object.keys(enabledFeatures).reduce((gates, enabledFeature) => {
    if (enabledFeatures[enabledFeature]) {
      gates.push(ENABLED_FEATURES_GATE_MAP[enabledFeature]);
    }
    return gates;
  }, []);
};
async function getJsRenderingGates(portalId, env2, personalAccessKey) {
  const {
    data: { enabledFeatures }
  } = await fetchAccessToken(personalAccessKey, env2, portalId);
  const envGates = getGatesFromEnv();
  const gates = mapEnabledFeaturesToGates(enabledFeatures);
  const mergedGates = [...envGates, ...gates];
  process.env.GATES = mergedGates.join(",");
  return mergedGates;
}

// src/lib/cliUtils.ts
import process2 from "process";
import os from "os";
import tty from "tty";
var COMPONENT_TYPES = Object.freeze({
  privateApp: "private-app",
  publicApp: "public-app",
  hublTheme: "hubl-theme"
});
var CONFIG_FILES = {
  [COMPONENT_TYPES.privateApp]: "app.json",
  [COMPONENT_TYPES.publicApp]: "public-app.json",
  [COMPONENT_TYPES.hublTheme]: "theme.json"
};
function hasNewDirectoryStructure(platformVersion) {
  return parseFloat(platformVersion) >= 2025.2;
}
var { env } = process2;
function translateLevel(level) {
  if (level === 0) {
    return {
      level,
      hasBasic: false,
      has256: false,
      has16m: false
    };
  }
  return {
    level,
    hasBasic: true,
    has256: level >= 2,
    has16m: level >= 3
  };
}
function _supportsColor(haveStream, { streamIsTTY } = {}) {
  if (haveStream && !streamIsTTY) {
    return 0;
  }
  const min = 0;
  if (env.TERM === "dumb") {
    return min;
  }
  if (hasFlag("noColor")) {
    return 0;
  }
  if (process2.platform === "win32") {
    const osRelease = os.release().split(".");
    if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
      return Number(osRelease[2]) >= 14931 ? 3 : 2;
    }
    return 1;
  }
  if ("CI" in env) {
    if ([
      "TRAVIS",
      "CIRCLECI",
      "APPVEYOR",
      "GITLAB_CI",
      "GITHUB_ACTIONS",
      "BUILDKITE",
      "DRONE"
    ].some((sign) => sign in env) || env.CI_NAME === "codeship") {
      return 1;
    }
    return min;
  }
  if ("TF_BUILD" in env && "AGENT_NAME" in env) {
    return 1;
  }
  if (env.COLORTERM === "truecolor") {
    return 3;
  }
  if ("TERM_PROGRAM" in env) {
    const version = Number.parseInt(
      (env.TERM_PROGRAM_VERSION || "").split(".")[0],
      10
    );
    switch (env.TERM_PROGRAM) {
      case "iTerm.app":
        return version >= 3 ? 3 : 2;
      case "Apple_Terminal":
        return 2;
    }
  }
  if (/-256(color)?$/i.test(env.TERM)) {
    return 2;
  }
  if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
    return 1;
  }
  if ("COLORTERM" in env) {
    return 1;
  }
  return min;
}
function createSupportsColor(stream2, options = {}) {
  const level = _supportsColor(stream2, {
    streamIsTTY: stream2 && stream2.isTTY,
    ...options
  });
  return translateLevel(level);
}
var supportsColor = {
  createSupportsColor,
  stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
  stderr: createSupportsColor({ isTTY: tty.isatty(2) })
};
function hasFlag(flag, argv = process2.argv) {
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
  const position = argv.indexOf(prefix + flag);
  const terminatorPosition = argv.indexOf("--");
  return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
}

// src/createDevServer.ts
import {
  getConfigAccountIfExists as getConfigAccountIfExists6,
  getConfigDefaultAccountIfExists,
  validateConfig
} from "@hubspot/local-dev-lib/config";
import { fetchSecrets } from "@hubspot/local-dev-lib/api/secrets";
import { PERSONAL_ACCESS_KEY_AUTH_METHOD } from "@hubspot/local-dev-lib/constants/auth";

// src/proxyPage/fetchDomains.ts
import { http as hsCliHttp12 } from "@hubspot/local-dev-lib/http";

// src/lib/errors.ts
var MISSING_SCOPE_ERROR_PREFIX = `Your personal access key is missing required scopes fetch domains.
You may need to re-generate a new personal access key with the required scopes and re-run \`hs-auth\`, or you may not have this functionality enabled in your account
`;
var OAUTH_ERROR_REGEX = /^This oauth-token \([\w]+\) does not have proper permissions!/;
var NOT_PUBLIC_USE_ERROR = `The scope needed for this API call isn't available for public use`;
var MissingScopeError = class extends Error {
  constructor(error) {
    let messageEnd = "";
    if (error.error.message.match(OAUTH_ERROR_REGEX)) {
      messageEnd = error.error.message;
    }
    super(`${MISSING_SCOPE_ERROR_PREFIX}
${messageEnd}`);
    Object.setPrototypeOf(this, MissingScopeError.prototype);
  }
};
function logMissingScopeWarning(error) {
  console.warn(error.message);
}
function isMissingScopeError(error) {
  return error.statusCode === 403 && (error.error.message.match(OAUTH_ERROR_REGEX) || error.error.message.startsWith(NOT_PUBLIC_USE_ERROR));
}
function handleSecretsError(error) {
  if (error && error.statusCode && error.error) {
    const { statusCode, error: errorDetails } = error;
    if ((errorDetails == null ? void 0 : errorDetails.category) === "MISSING_SCOPES") {
      console.log(
        "\nMissing scopes for secrets.",
        "\nSecrets require Serverless functions which are scoped to Enterprise portals.\n"
      );
    } else {
      console.error(`Error ${statusCode}: ${errorDetails.message}`);
      if (errorDetails.correlationId) {
        console.error(`Correlation ID: ${errorDetails.correlationId}`);
      }
      if (errorDetails.category) {
        console.error(`Category: ${errorDetails.category}`);
      }
      if (errorDetails.links) {
        if (errorDetails.links.support) {
          console.error(`Support URL: ${errorDetails.links.support}`);
        }
        if (errorDetails.links.forum) {
          console.error(`Forum URL: ${errorDetails.links.forum}`);
        }
      }
    }
  } else {
    console.error("Unexpected error structure:", error);
  }
}

// src/proxyPage/fetchDomains.ts
async function fetchDomains(portalId) {
  try {
    const result = (await hsCliHttp12.get(portalId, {
      url: `/cms/v3/domains`,
      params: { portalId },
      responseType: "json"
    })).data;
    return result.results;
  } catch (error) {
    if (isMissingScopeError(error)) {
      throw new MissingScopeError(error);
    }
    throw error;
  }
}
async function fetchWebsiteDomainNames(portalId) {
  const domains = await fetchDomains(portalId);
  const filteredDomains = domains.filter((domain) => {
    return domain.isUsedForBlogPost || domain.isUsedForSitePage || domain.isUsedForLandingPage;
  });
  const domainNames = filteredDomains.map((r) => r.domain);
  return domainNames;
}

// src/lib/validateHSPlatform.ts
import path14 from "path";
import fs5 from "fs";
import select from "@inquirer/select";
import { http as hsCliHttp13 } from "@hubspot/local-dev-lib/http";
var HSPROJECT_JSON = "hsproject.json";
function checkFileExists(filePath) {
  return fs5.existsSync(filePath) && fs5.statSync(filePath).isFile();
}
function findHSProjectJson(startPath) {
  let currentDir = startPath;
  let dirLevel = 0;
  const maxDirLevel = 4;
  while (path14.dirname(currentDir) !== currentDir && dirLevel < maxDirLevel) {
    const filePath = path14.join(currentDir, HSPROJECT_JSON);
    if (checkFileExists(filePath)) {
      return filePath;
    }
    currentDir = path14.dirname(currentDir);
    dirLevel++;
  }
  console.log(
    `'${HSPROJECT_JSON}' not found in any parent of dev server target`
  );
  return null;
}
async function validateHSPlatform(projectConfigPath, portalId) {
  if (projectConfigPath === null) {
    console.log(
      `Unable to find local ${HSPROJECT_JSON}, skipping platform version validation.`
    );
    return false;
  }
  const hsProjectJSONContents = fs5.readFileSync(projectConfigPath, "utf8");
  const hsProjectJSONData = JSON.parse(hsProjectJSONContents);
  const { platformVersion } = hsProjectJSONData;
  let platformVersionResult;
  try {
    platformVersionResult = (await hsCliHttp13.get(portalId, {
      url: `developer/projects/v1/platformVersion`,
      responseType: "json"
    })).data;
  } catch (e) {
    console.error(e.message);
    console.log(
      "Unable to find active platform versions, skipping platform version validation."
    );
    return false;
  }
  if (platformVersion === void 0 || !platformVersionResult.activePlatformVersions.includes(platformVersion)) {
    const answer = await select({
      message: 'Your local "hsproject.json" does not have a valid platform version, please select a valid platform version. You can read more about Platform Versioning here https://developers.hubspot.com/docs/platform/platform-versioning',
      choices: platformVersionResult.activePlatformVersions.map(
        (versionNumber) => ({
          name: versionNumber,
          value: versionNumber
        })
      )
    });
    hsProjectJSONData.platformVersion = answer;
    try {
      fs5.writeFileSync(
        projectConfigPath,
        JSON.stringify(hsProjectJSONData, void 0, 2),
        "utf8"
      );
      return true;
    } catch (e) {
      console.error(
        `unable to write updated valid platform version, please make sure platformVersion in "${HSPROJECT_JSON}" is one of ${platformVersionResult.activePlatformVersions}`
      );
      return false;
    }
  }
  return true;
}

// src/createDevServer.ts
import { http as hsCliHttp14 } from "@hubspot/local-dev-lib/http";

// ../cms-js-internal/dist/buildFieldsTypes.js
import { writeFileSync } from "fs";
import ts from "typescript";
var fieldTypeNameByType = {
  alignment: "AlignmentFieldType",
  audioplayer: "AudioFieldType",
  backgroundimage: "BackgroundImageFieldType",
  blog: "BlogFieldType",
  boolean: "BooleanFieldType",
  border: "BorderFieldType",
  choice: "ChoiceFieldType",
  color: "ColorFieldType",
  crmobject: "CrmObjectFieldType",
  cta: "CtaFieldType",
  date: "DateFieldType",
  datetime: "DateTimeFieldType",
  email: "EmailFieldType",
  embed: "EmbedFieldType",
  file: "FileFieldType",
  followupemail: "FollowUpEmailFieldType",
  font: "FontFieldType",
  form: "FormFieldType",
  gradient: "GradientFieldType",
  group: "GroupFieldType",
  html: "HtmlFieldType",
  hubdbrow: "HubDbRowFieldType",
  hubdbtable: "HubDbTableFieldType",
  hubl: "HublFieldType",
  icon: "IconFieldType",
  image: "ImageFieldType",
  link: "LinkFieldType",
  logo: "LogoFieldType",
  meeting: "MeetingFieldType",
  menu: "MenuFieldType",
  number: "NumberFieldType",
  page: "PageFieldType",
  payment: "PaymentFieldType",
  podcast: "PodcastFieldType",
  richtext: "RichTextFieldType",
  salesforcecampaign: "SfdcCamapaignFieldType",
  simplemenu: "SimpleMenuFieldType",
  spacing: "SpacingFieldType",
  survey: "SurveyFieldType",
  tag: "TagFieldType",
  textalignment: "TextAlignmentFieldType",
  text: "TextFieldType",
  url: "UrlFieldType",
  videoplayer: "VideoFieldType",
  workflow: "WorkflowFieldType"
};
function getFieldEntries(fields) {
  if (!Array.isArray(fields)) {
    return void 0;
  }
  return fields.filter((field) => field.name && field.type).map((field) => {
    const { name, type } = field;
    const fieldType = fieldTypeNameByType[type];
    if (!fieldType) {
      return void 0;
    }
    const entry = {
      type: fieldType,
      name,
      isRepeater: "occurrence" in field,
      isRequired: !!field.required,
      choices: (
        // Choices are pair [value, label] but only the value is printed to the page, so flatten it.
        "choices" in field ? field.choices.map(([value, label]) => value) : void 0
      ),
      children: []
    };
    if (fieldType === "GroupFieldType" && "children" in field) {
      const children = getFieldEntries(field.children);
      return { ...entry, children };
    }
    return entry;
  }).filter((entry) => entry !== void 0);
}
var INVALID_IMPORTS = ["ChoiceFieldType", "GroupFieldType"];
var FIELD_GROUP_TYPE = "FieldGroupWithChildren";
var REPEATER_GROUP_TYPE = "RepeaterGroup";
var REQUIRED_TYPE = "RequiredField";
var DEFAULT_VALUES_TYPE = "DefaultValues";
var CMS_COMPONENTS = "@hubspot/cms-components";
var CMS_COMPONENTS_FIELD_TYPES = `${CMS_COMPONENTS}/fields`;
var AUTO_GEN_COMMENT = "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.";
var createPropertySignature = (identifier, type, hasQuestionToken = false) => ts.factory.createPropertySignature(
  [],
  identifier,
  hasQuestionToken ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : void 0,
  type
);
var createUnionTypeFromArray = (values) => ts.factory.createUnionTypeNode(
  values.map(
    (value) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(value))
  )
);
var buildTypeFromField = (field, additionalNode) => {
  const imports = [field.type];
  const identifier = ts.factory.createIdentifier(field.name);
  const baseType = ts.factory.createTypeReferenceNode(field.type);
  const requiredType = ts.factory.createTypeReferenceNode(REQUIRED_TYPE, [
    baseType
  ]);
  let finalType = field.isRequired ? requiredType : baseType;
  if (field.choices) {
    finalType = createUnionTypeFromArray(field.choices);
  }
  if (field.isRequired) {
    imports.push(REQUIRED_TYPE);
  }
  if (additionalNode) {
    const typeLiteral = ts.isTypeLiteralNode(additionalNode) ? additionalNode : ts.factory.createTypeLiteralNode([additionalNode]);
    const genericType = field.isRepeater ? REPEATER_GROUP_TYPE : FIELD_GROUP_TYPE;
    imports.push(genericType);
    finalType = ts.factory.createTypeReferenceNode(genericType, [typeLiteral]);
  }
  return {
    type: createPropertySignature(
      identifier,
      finalType,
      !field.isRequired && !additionalNode
    ),
    imports
  };
};
var filterUnusedImports = (imports, type) => {
  const usedImports = /* @__PURE__ */ new Set();
  const visit = (node) => {
    if (ts.isTypeReferenceNode(node)) {
      const typeName = node.typeName;
      if ("escapedText" in typeName) {
        usedImports.add(typeName.escapedText.toString());
      }
    }
    ts.forEachChild(node, visit);
  };
  visit(type);
  return imports.filter((name) => usedImports.has(name));
};
function getImportDeclaration(imports, moduleSpecifier) {
  const importSpecifiers = Array.from(imports).map(
    (importName) => ts.factory.createImportSpecifier(
      true,
      void 0,
      ts.factory.createIdentifier(importName)
    )
  );
  const namedImports = ts.factory.createNamedImports(importSpecifiers);
  return ts.factory.createImportDeclaration(
    [],
    [],
    ts.factory.createImportClause(false, void 0, namedImports),
    ts.factory.createStringLiteral(moduleSpecifier)
  );
}
function getFieldTypes(fields) {
  const imports = [];
  const types = fields.map((field) => {
    if (field.children) {
      const childrenResult = getFieldTypes(field.children);
      imports.push(...childrenResult.imports);
      if (childrenResult.types.length) {
        const subType = ts.factory.createTypeLiteralNode(childrenResult.types);
        const { type: type2, imports: newImports2 } = buildTypeFromField(
          field,
          subType
        );
        imports.push(...newImports2);
        return type2;
      }
    }
    const { type, imports: newImports } = buildTypeFromField(field);
    imports.push(...newImports);
    return type;
  });
  const validImports = Array.from(
    new Set(imports.filter((name) => !INVALID_IMPORTS.includes(name)))
  );
  return { types, imports: validImports };
}
function constructFinalType(fields, typeName) {
  const { types, imports } = getFieldTypes(fields);
  const baseType = ts.factory.createTypeAliasDeclaration(
    [],
    [],
    "",
    void 0,
    ts.factory.createTypeLiteralNode(types)
  );
  const wrappedType = ts.factory.createTypeReferenceNode(DEFAULT_VALUES_TYPE, [
    baseType.type
  ]);
  const finalType = ts.factory.createTypeAliasDeclaration(
    [],
    [],
    typeName,
    void 0,
    wrappedType
  );
  const filteredImports = filterUnusedImports(imports, finalType);
  const importDeclaration = getImportDeclaration(
    [...filteredImports, DEFAULT_VALUES_TYPE],
    CMS_COMPONENTS_FIELD_TYPES
  );
  const defaultExport = ts.factory.createExportDefault(
    ts.factory.createIdentifier(typeName)
  );
  return [importDeclaration, finalType, defaultExport];
}
function writeFieldsType(fields, fileName, typeName) {
  const entries = getFieldEntries(fields);
  if (!entries) {
    return false;
  }
  try {
    const file = ts.createSourceFile(
      fileName,
      "",
      ts.ScriptTarget.ESNext,
      false,
      ts.ScriptKind.TS
    );
    const printer = ts.createPrinter();
    const nodes = constructFinalType(entries, typeName);
    const comments = [
      AUTO_GEN_COMMENT,
      "Removing the above comment will disable type generation for this module",
      "This file was created by @hubspot/cms-dev-server, for more information see https://github.hubspot.com/cms-react/reference/js-modules.html#module-fields"
    ].map((comment) => `// ${comment}`);
    const typeResult = nodes.map(
      (node) => printer.printNode(ts.EmitHint.Unspecified, node, file)
    );
    const result = [...comments, ...typeResult].join("\n");
    writeFileSync(fileName, result);
    return true;
  } catch (e) {
    console.error(e);
    return false;
  }
}

// src/lib/watchFieldsUpdates.ts
import fs6 from "fs";
import path15 from "path";
import readline from "readline";
var lastSerializedFieldsCache = {};
var formatAsTypeName = (str) => {
  const typeName = `${str.replace(/[^a-zA-Z0-9_$]/g, "_")}FieldsType`;
  const validFirstChar = /^[A-Za-z_$]/.test(str.charAt(0));
  return validFirstChar ? typeName : `_${typeName}`;
};
var isInModulesFolder = (filePath, projectRoot) => {
  const getEntryPathFromId = (id) => {
    return id.startsWith(projectRoot) ? id.replace(`${projectRoot}${path15.sep}`, "") : "";
  };
  const currentModuleId = path15.normalize(filePath);
  const moduleEntryPath = getEntryPathFromId(currentModuleId);
  const subFolderTokens = moduleEntryPath.split(path15.sep);
  return {
    inModuleFolder: subFolderTokens[0] === "components" && subFolderTokens[1] === "modules",
    isRootModuleFile: subFolderTokens.length === 3
  };
};
var fileContainsAutoGenComment = async (filePath) => {
  if (!fs6.existsSync(filePath))
    return true;
  const stream2 = fs6.createReadStream(filePath);
  const reader = readline.createInterface({ input: stream2 });
  const firstLine = await new Promise(
    (resolve2) => reader.once("line", (line) => resolve2(line.trim()))
  );
  reader.close();
  stream2.close();
  return firstLine && firstLine === `// ${AUTO_GEN_COMMENT}`;
};
var getIndexFile = (filePath, projectRoot) => {
  const { inModuleFolder, isRootModuleFile } = isInModulesFolder(
    filePath,
    projectRoot
  );
  if (!inModuleFolder)
    return void 0;
  if (isRootModuleFile)
    return { indexFilePath: filePath, isRootModuleFile };
  const dir = path15.dirname(filePath);
  const files = fs6.readdirSync(dir);
  const indexFileName = files.find((file) => file.startsWith("index."));
  return indexFileName ? { indexFilePath: path15.join(dir, indexFileName), isRootModuleFile } : void 0;
};
var getIndexFileFields = async (indexFilePath, indexFileName, viteServer) => {
  let indexFile;
  let renderFieldsToJson;
  try {
    indexFile = await viteServer.ssrLoadModule(indexFilePath);
    const internalSsrPath = packagePath(import.meta.url, "internalSsr");
    ({ renderFieldsToJson } = await viteServer.ssrLoadModule(internalSsrPath));
  } catch (e) {
    return void 0;
  }
  if (!indexFile.fields)
    return void 0;
  const fields = indexFile.fields;
  const renderedFieldsJson = renderFieldsToJson(fields, indexFileName);
  const isValidFields = Array.isArray(renderedFieldsJson);
  return isValidFields ? renderedFieldsJson : void 0;
};
var maybeUpdateFields = async (filePath, viteServer, projectRoot) => {
  const indexInfo = getIndexFile(filePath, projectRoot);
  if (!indexInfo)
    return;
  const { indexFilePath, isRootModuleFile } = indexInfo;
  const indexFileName = path15.parse(indexFilePath).name;
  const isTypeFile = filePath.endsWith(".types.ts");
  if (isTypeFile)
    return;
  const fields = await getIndexFileFields(
    indexFilePath,
    indexFileName,
    viteServer
  );
  if (fields) {
    const typeFileName = isRootModuleFile ? `${indexFileName}.fields.types.ts` : "fields.type.ts";
    const typeFilePath = path15.join(path15.dirname(filePath), typeFileName);
    const lastSerializedFields = lastSerializedFieldsCache[typeFilePath];
    const serializedFields = JSON.stringify(fields);
    if (lastSerializedFields === serializedFields)
      return;
    const hasAutoGenComment = await fileContainsAutoGenComment(typeFilePath);
    if (!hasAutoGenComment)
      return;
    const moduleFolderName = path15.basename(path15.dirname(filePath));
    const outputTypeName = formatAsTypeName(moduleFolderName);
    const didSucceed = writeFieldsType(fields, typeFilePath, outputTypeName);
    if (didSucceed) {
      lastSerializedFieldsCache[typeFilePath] = serializedFields;
    }
    const pathToLog = isRootModuleFile ? `${moduleFolderName}/${indexFileName}` : moduleFolderName;
    const successMsg = `Successfully generated types for ${pathToLog}`;
    const errorMsg = `Failed to generate types for ${pathToLog}`;
    const message = didSucceed ? successMsg : errorMsg;
    console.log(wrapMessageInColor(didSucceed ? "green" : "red", message));
  }
};
var startFieldsTypeGenWatcher = (viteServer, projectRoot) => {
  const { moduleSubpaths } = findAllModulesInRoot(projectRoot);
  moduleSubpaths.forEach((modulePath) => {
    const resolvedPath = path15.resolve(projectRoot, modulePath);
    maybeUpdateFields(resolvedPath, viteServer, projectRoot);
  });
  const watchCallback = (filePath) => maybeUpdateFields(filePath, viteServer, projectRoot);
  viteServer.watcher.on("add", watchCallback).on("change", watchCallback);
};

// src/lib/configHelpers.ts
function getSecretNamesFromConfig(config) {
  var _a, _b;
  if ("secretNames" in config && ((_a = config.secretNames) == null ? void 0 : _a.length) > 0) {
    return config.secretNames;
  }
  if ("secret_names" in config && ((_b = config.secret_names) == null ? void 0 : _b.length) > 0) {
    return config.secret_names;
  }
  return [];
}

// src/createDevServer.ts
var BASE_PATH = "/";
var PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3e3;
var SHADOW_PORT = 1442;
var STORYBOOK_PORT = process.env.STORYBOOK_PORT ? parseInt(process.env.STORYBOOK_PORT, 10) : 3123;
function getWebRootProjectComponentFolder(absoluteWebRoot, projectConfigPath) {
  const pathSegments = absoluteWebRoot.replace(/\/$/, "").split("/");
  const themeFolderName = pathSegments[pathSegments.length - 1];
  if (!projectConfigPath) {
    return themeFolderName;
  }
  try {
    const projectDir = path16.dirname(projectConfigPath);
    const configContent = fs7.readFileSync(projectConfigPath, "utf8");
    const projectConfig = JSON.parse(configContent);
    const isNewStructure = hasNewDirectoryStructure(
      projectConfig.platformVersion
    );
    if (isNewStructure) {
      const srcDir = projectConfig.srcDir || "src";
      const hsmetaPath = path16.join(
        projectDir,
        srcDir,
        "theme",
        "theme-hsmeta.json"
      );
      if (fs7.existsSync(hsmetaPath)) {
        const hsmetaContent = fs7.readFileSync(hsmetaPath, "utf8");
        const hsmeta = JSON.parse(hsmetaContent);
        if (hsmeta.uid) {
          return hsmeta.uid;
        }
      }
    }
  } catch (e) {
    console.warn(
      "Could not determine project component folder from config:",
      e.message
    );
  }
  return themeFolderName;
}
async function createDevServer(webRoot, storybook, hubspotCliConfigPathOption, hubspotCliAccountNameOption, sslEnabledOption, fieldGenEnabledOption, themePreviewOptions, fieldBuilderEnabled) {
  let authedPortalId = null;
  let authedEnv = null;
  let jsRenderingGates = [];
  let personalAccessKey = null;
  let secretNames = [];
  let secretNamesFromConfig = [];
  if (hubspotCliConfigPathOption) {
    process.env.HUBSPOT_CONFIG_PATH = hubspotCliConfigPathOption;
  }
  if (hubspotCliConfigPathOption && hubspotCliAccountNameOption) {
    console.log(
      `Loading HS auth (account = ${hubspotCliAccountNameOption}) configuration at: ${hubspotCliConfigPathOption}`
    );
  } else if (hubspotCliConfigPathOption) {
    console.log(
      `Loading HS auth configuration at: ${hubspotCliConfigPathOption}`
    );
  } else if (hubspotCliAccountNameOption) {
    console.log(
      `Loading HS auth (account = ${hubspotCliAccountNameOption}) configuration.`
    );
  }
  const cmsAssetConfig = getCMSAssetConfig(webRoot);
  secretNamesFromConfig = getSecretNamesFromConfig(cmsAssetConfig);
  const { isValid } = validateConfig();
  if (isValid) {
    const account = hubspotCliAccountNameOption ? getConfigAccountIfExists6(hubspotCliAccountNameOption) : getConfigDefaultAccountIfExists();
    if (!account) {
      console.error(
        hubspotCliAccountNameOption ? `Couldn't find ${hubspotCliAccountNameOption} in your hubspot.config.yaml` : `No default account found. Run 'hs auth' first.`
      );
      process.exit(1);
    }
    authedPortalId = account == null ? void 0 : account.accountId;
    const env2 = account == null ? void 0 : account.env;
    if (!env2) {
      throw new Error(
        `No environment found for account ${hubspotCliAccountNameOption} from hubspot.config.yaml`
      );
    }
    authedEnv = env2;
    personalAccessKey = (account == null ? void 0 : account.authType) === PERSONAL_ACCESS_KEY_AUTH_METHOD.value ? account == null ? void 0 : account.personalAccessKey : null;
    if (personalAccessKey) {
      try {
        jsRenderingGates = await getJsRenderingGates(
          authedPortalId,
          authedEnv,
          personalAccessKey
        );
      } catch (e) {
        console.warn(
          `Unable to get gating information. Gated features will not be available in the local dev server.`
        );
      }
    }
    if (cmsAssetConfig) {
      try {
        const secretsResponse = (await fetchSecrets(authedPortalId)).data;
        if (secretNamesFromConfig && secretsResponse) {
          secretNames = secretsResponse.results.filter(
            (secretName) => secretNamesFromConfig.includes(secretName)
          );
          if (secretNames.length < secretNamesFromConfig.length) {
            const missingSecrets = secretNamesFromConfig.filter(
              (secretName) => secretsResponse.results.includes(secretName) === false
            );
            console.error(
              `Secrets ${missingSecrets.join(
                ", "
              )} could not be found as initialized for this account, be sure to use \`hs secrets add\``
            );
          }
        }
      } catch (e) {
        handleSecretsError(e);
        console.log(e);
      }
    }
  } else {
    console.warn(
      `Couldn't find an account to use, make sure there is hubspot.config.yaml in this folder (or a parent).
If needed you can refer to another config file with --config.

Local proxy functionality and module preview routes will not work without setting up authentication. You can work purely on modules locally at "/module/[module_name]", however the experience may be degraded due to missing account data.`
    );
    secretNames = secretNamesFromConfig;
  }
  setTrackingInfo(authedPortalId, authedEnv);
  sendTrackingRequest("start-dev-server");
  let domainsToProxy = [];
  if (authedPortalId) {
    try {
      const portalDomains = await fetchWebsiteDomainNames(authedPortalId);
      domainsToProxy = (process.env.DOMAINS_TO_PROXY || "").split(",").filter((d) => !!d);
      domainsToProxy = [...domainsToProxy, ...portalDomains];
    } catch (e) {
      if (e instanceof MissingScopeError) {
        logMissingScopeWarning(e);
      } else {
        const failedDomainFetchMessages = [
          "Failed to fetch the portal's domains, as a result:",
          "- HTTPS proxying won't work with them.",
          "- Proxying to serverless functions won't work."
        ].map((msg) => wrapMessageInColor("yellow", msg)).join("\n");
        console.warn(failedDomainFetchMessages);
      }
    }
  }
  let authedHublet;
  try {
    const accountInformation = (await hsCliHttp14.get(authedPortalId, {
      url: "/account-info/v3/details"
    })).data;
    authedHublet = accountInformation.dataHostingLocation;
  } catch (e) {
    authedHublet = "na1";
  }
  const absoluteWebRoot = normalizePath10(path16.resolve(process.cwd(), webRoot));
  const projectConfigPath = findHSProjectJson(absoluteWebRoot);
  const webRootProjectComponentFolder = getWebRootProjectComponentFolder(
    absoluteWebRoot,
    projectConfigPath
  );
  if (authedPortalId) {
    await validateHSPlatform(projectConfigPath, authedPortalId);
  }
  let _localPreviewToken = null;
  let _tokenStatus;
  if (themePreviewOptions) {
    const { localPreviewToken, tokenStatus } = await initiatePreviewSession(
      authedPortalId,
      absoluteWebRoot,
      themePreviewOptions
    );
    _localPreviewToken = localPreviewToken;
    _tokenStatus = tokenStatus;
  }
  const viteServer = await createViteDevServer_default(
    absoluteWebRoot,
    PORT,
    sslEnabledOption,
    domainsToProxy,
    jsRenderingGates,
    secretNames
  );
  if (fieldGenEnabledOption) {
    const normalizedAbsoluteWebRoot = path16.normalize(absoluteWebRoot);
    startFieldsTypeGenWatcher(viteServer, normalizedAbsoluteWebRoot);
  }
  const viteHTTPSConfig = viteServer.config.server.https;
  const httpsKey = viteHTTPSConfig ? viteHTTPSConfig.key : null;
  const httpsCert = viteHTTPSConfig ? viteHTTPSConfig.cert : null;
  const projectName = projectConfigPath ? getProjectNameFromHSConfig(projectConfigPath) : "";
  const httpServers = [];
  const expressServer = express2();
  expressServer.locals.devServerHost = "hslocal.net";
  expressServer.locals.devServerPort = PORT;
  expressServer.locals.webRoot = webRoot;
  expressServer.locals.viteServer = viteServer;
  expressServer.locals.authedPortalId = authedPortalId;
  expressServer.locals.authedEnv = authedEnv;
  expressServer.locals.authedHublet = authedHublet;
  expressServer.locals.storybookEnabled = storybook;
  expressServer.locals.storybookPort = STORYBOOK_PORT;
  expressServer.locals.projectName = projectName;
  expressServer.locals.projectComponentPath = webRootProjectComponentFolder;
  expressServer.locals.jsRenderingGates = jsRenderingGates;
  expressServer.locals.domainsToProxy = domainsToProxy;
  expressServer.locals.localPreviewToken = _localPreviewToken;
  expressServer.locals.sslEnabled = sslEnabledOption;
  expressServer.use(bodyParser.json());
  const __dirname = path16.dirname(url2.fileURLToPath(new URL(import.meta.url)));
  let appWebRoot = normalizePath10(path16.resolve(__dirname, "../app"));
  if (true) {
    appWebRoot = path16.join(__dirname, "app");
  }
  const appViteServer = await createAppServer_default(
    appWebRoot,
    PORT,
    sslEnabledOption
  );
  const appLocals = {
    themeWebRoot: absoluteWebRoot,
    authedPortalId,
    authedEnv,
    authedHublet,
    projectName,
    webRootProjectComponentFolder,
    localPreviewToken: _localPreviewToken,
    sslEnabled: sslEnabledOption,
    fieldBuilderEnabled,
    appWebRoot,
    appViteServer
  };
  expressServer.locals.appLocals = appLocals;
  expressServer.use(
    BASE_PATH,
    await createDevServerRoutes_default(
      viteServer,
      appLocals,
      storybook ? STORYBOOK_PORT : null
    )
  );
  if (sslEnabledOption) {
    if (httpsKey && httpsCert) {
      const { server, innerHTTPServer, innerHTTPSServer } = createHttpsRedirectingServer(
        { key: httpsKey, cert: httpsCert },
        expressServer
      );
      server.listen(PORT);
      httpServers.push(server);
      httpServers.push(innerHTTPServer);
      httpServers.push(innerHTTPSServer);
    } else {
      console.error("Failed to start a HTTPS server, try --no-ssl");
      process.exit(1);
    }
  } else {
    const httpServer = http3.createServer(expressServer);
    httpServer.listen(PORT);
    httpServers.push(httpServer);
  }
  if (!process.env.IN_CODESANDBOX && !process.env.CODESANDBOX_HOST) {
    startShadowDevServer(
      PORT,
      SHADOW_PORT,
      themePreviewOptions ? themePreviewOptions.dest : ""
    );
  }
  let extraServerInfo = "";
  const protocol = sslEnabledOption ? "https" : "http";
  if (authedPortalId) {
    extraServerInfo += `, hubid=${authedPortalId}`;
  }
  if (authedEnv && authedEnv !== "prod") {
    extraServerInfo += `, env=${authedEnv}`;
  }
  const startMessage = projectName ? `
HubSpot CMS dev server ${projectName ? `hosting: ${projectName}/` : "running"}${expressServer.locals.projectComponentPath} (at ${protocol}://hslocal.net:${PORT}${extraServerInfo})
` : `
HubSpot CMS dev server running at ${protocol}://hslocal.net:${PORT}${extraServerInfo}
`;
  console.log(startMessage);
  if (storybook) {
    const packageRoot = path16.dirname(url2.fileURLToPath(import.meta.url));
    const configPath = path16.resolve(packageRoot, "./storybook-main");
    sendTrackingRequest("start-storybook");
    let storybookBin;
    try {
      const sbPackagePath = await import.meta.resolve("storybook/package.json");
      const sbPackageDir = path16.dirname(url2.fileURLToPath(sbPackagePath));
      const packageJson = JSON.parse(
        fs7.readFileSync(path16.join(sbPackageDir, "package.json"), "utf-8")
      );
      storybookBin = path16.join(
        sbPackageDir,
        packageJson.bin.storybook || packageJson.bin
      );
    } catch (e) {
      console.error(
        wrapMessageInColor(
          "red",
          "Could not find storybook dependencies. The --storybook flag will be ignored."
        )
      );
      return;
    }
    console.log(
      wrapMessageInColor(
        "yellow",
        `Starting storybook server on port ${STORYBOOK_PORT}`
      )
    );
    const storybookProcess = spawn2(
      storybookBin,
      [
        "dev",
        "-p",
        STORYBOOK_PORT.toString(),
        "-c",
        configPath,
        "--quiet",
        "--no-open"
      ],
      {
        cwd: process.cwd(),
        env: {
          ...process.env,
          portalId: authedPortalId.toString(),
          hsEnv: authedEnv,
          hublet: authedHublet,
          WEB_ROOT: path16.join(webRoot, "components")
        },
        stdio: "inherit"
      }
    );
    storybookProcess.on("error", (err) => {
      console.error(
        wrapMessageInColor(
          "red",
          "Failed to start storybook. The --storybook flag will be ignored."
        )
      );
      console.error(err);
    });
  }
  return {
    close: () => {
      const serverClosePromises = httpServers.map(
        (server) => new Promise((resolve2) => {
          server.close(() => {
            resolve2(null);
          });
        })
      );
      return Promise.allSettled([
        ...serverClosePromises,
        viteServer.close(),
        appViteServer.close()
      ]);
    }
  };
}
var createDevServer_default = createDevServer;
export {
  createDevServer_default as createDevServer,
  createViteDevServer_default as createViteDevServer
};
